import { DeepExclude } from './DeepExclude.cjs';
import { IsPlainObject, Primitives, IsLiteral, ValueOf, Compute, Cast, Equal, Extends, Not, All, NonLiteralPrimitive } from './helpers.cjs';
import type { Matcher, Pattern, ToExclude } from './Pattern.cjs';
type OptionalKeys<p> = ValueOf<{
    [k in keyof p]: p[k] extends Matcher<any, any, infer matcherType> ? matcherType extends 'optional' ? k : never : never;
}>;
type ReduceUnion<tuple extends any[], output = never> = tuple extends readonly [
    infer p,
    ...infer tail
] ? ReduceUnion<tail, output | InvertPattern<p>> : output;
type ReduceIntersection<tuple extends any[], output = unknown> = tuple extends readonly [infer p, ...infer tail] ? ReduceIntersection<tail, output & InvertPattern<p>> : output;
/**
 * ### InvertPattern
 * Since patterns have special wildcard values, we need a way
 * to transform a pattern into the type of value it represents
 */
export type InvertPattern<p> = p extends Matcher<infer input, infer narrowed, infer matcherType, any> ? {
    not: ToExclude<InvertPattern<narrowed>>;
    select: InvertPattern<narrowed>;
    array: InvertPattern<narrowed>[];
    optional: InvertPattern<narrowed> | undefined;
    and: ReduceIntersection<Cast<narrowed, any[]>>;
    or: ReduceUnion<Cast<narrowed, any[]>>;
    default: [narrowed] extends [never] ? input : narrowed;
}[matcherType] : p extends Primitives ? p : p extends readonly (infer pp)[] ? p extends readonly [infer p1, infer p2, infer p3, infer p4, infer p5] ? [
    InvertPattern<p1>,
    InvertPattern<p2>,
    InvertPattern<p3>,
    InvertPattern<p4>,
    InvertPattern<p5>
] : p extends readonly [infer p1, infer p2, infer p3, infer p4] ? [
    InvertPattern<p1>,
    InvertPattern<p2>,
    InvertPattern<p3>,
    InvertPattern<p4>
] : p extends readonly [infer p1, infer p2, infer p3] ? [InvertPattern<p1>, InvertPattern<p2>, InvertPattern<p3>] : p extends readonly [infer p1, infer p2] ? [InvertPattern<p1>, InvertPattern<p2>] : p extends readonly [infer p1] ? [InvertPattern<p1>] : p extends readonly [] ? [] : InvertPattern<pp>[] : p extends Map<infer pk, infer pv> ? Map<pk, InvertPattern<pv>> : p extends Set<infer pv> ? Set<InvertPattern<pv>> : IsPlainObject<p> extends true ? OptionalKeys<p> extends infer optKeys ? [optKeys] extends [never] ? {
    [k in Exclude<keyof p, optKeys>]: InvertPattern<p[k]>;
} : Compute<{
    [k in Exclude<keyof p, optKeys>]: InvertPattern<p[k]>;
} & {
    [k in Cast<optKeys, keyof p>]?: InvertPattern<p[k]>;
}> : never : p;
export type ReduceIntersectionForExclude<tuple extends any[], i, output = unknown> = tuple extends readonly [infer p, ...infer tail] ? ReduceIntersectionForExclude<tail, i, output & InvertPatternForExcludeInternal<p, i, unknown>> : output;
export type ReduceUnionForExclude<tuple extends any[], i, output = never> = tuple extends readonly [infer p, ...infer tail] ? ReduceUnionForExclude<tail, i, output | InvertPatternForExcludeInternal<p, i, never>> : output;
type ExcludeIfExists<a, b> = [
    b
] extends [never] ? never : unknown extends a ? never : All<[
    Extends<a, NonLiteralPrimitive>,
    Not<IsLiteral<a>>,
    IsLiteral<b>
]> extends true ? never : DeepExclude<a, b>;
/**
 * ### InvertPatternForExclude
 */
export type InvertPatternForExclude<p, i> = Equal<p, Pattern<i>> extends true ? never : InvertPatternForExcludeInternal<p, i>;
type InvertPatternForExcludeInternal<p, i, empty = never> = [
    p
] extends [Primitives] ? IsLiteral<p> extends true ? p : IsLiteral<i> extends true ? p : empty : p extends Matcher<infer matchableInput, infer subpattern, infer matcherType, any, infer excluded> ? {
    select: InvertPatternForExcludeInternal<subpattern, i, empty>;
    array: i extends readonly (infer ii)[] ? InvertPatternForExcludeInternal<subpattern, ii, empty>[] : empty;
    optional: InvertPatternForExcludeInternal<subpattern, i, empty> | undefined;
    and: ReduceIntersectionForExclude<Cast<subpattern, any[]>, i>;
    or: ReduceUnionForExclude<Cast<subpattern, any[]>, i>;
    not: ExcludeIfExists<unknown extends matchableInput ? i : matchableInput, InvertPatternForExcludeInternal<subpattern, i>>;
    default: excluded;
}[matcherType] : p extends readonly (infer pp)[] ? i extends readonly (infer ii)[] ? p extends readonly [infer p1, infer p2, infer p3, infer p4, infer p5] ? i extends readonly [infer i1, infer i2, infer i3, infer i4, infer i5] ? readonly [
    InvertPatternForExcludeInternal<p1, i1, empty>,
    InvertPatternForExcludeInternal<p2, i2, empty>,
    InvertPatternForExcludeInternal<p3, i3, empty>,
    InvertPatternForExcludeInternal<p4, i4, empty>,
    InvertPatternForExcludeInternal<p5, i5, empty>
] : empty : p extends readonly [infer p1, infer p2, infer p3, infer p4] ? i extends readonly [infer i1, infer i2, infer i3, infer i4] ? readonly [
    InvertPatternForExcludeInternal<p1, i1, empty>,
    InvertPatternForExcludeInternal<p2, i2, empty>,
    InvertPatternForExcludeInternal<p3, i3, empty>,
    InvertPatternForExcludeInternal<p4, i4, empty>
] : empty : p extends readonly [infer p1, infer p2, infer p3] ? i extends readonly [infer i1, infer i2, infer i3] ? readonly [
    InvertPatternForExcludeInternal<p1, i1, empty>,
    InvertPatternForExcludeInternal<p2, i2, empty>,
    InvertPatternForExcludeInternal<p3, i3, empty>
] : empty : p extends readonly [infer p1, infer p2] ? i extends readonly [infer i1, infer i2] ? readonly [
    InvertPatternForExcludeInternal<p1, i1, empty>,
    InvertPatternForExcludeInternal<p2, i2, empty>
] : empty : p extends readonly [infer p1] ? i extends readonly [infer i1] ? readonly [InvertPatternForExcludeInternal<p1, i1, empty>] : empty : p extends readonly [] ? [] : InvertPatternForExcludeInternal<pp, ii, empty>[] : empty : p extends Map<infer pk, infer pv> ? i extends Map<any, infer iv> ? Map<pk, InvertPatternForExcludeInternal<pv, iv, empty>> : empty : p extends Set<infer pv> ? i extends Set<infer iv> ? Set<InvertPatternForExcludeInternal<pv, iv, empty>> : empty : IsPlainObject<p> extends true ? i extends object ? [keyof p & keyof i] extends [never] ? empty : OptionalKeys<p> extends infer optKeys ? [optKeys] extends [never] ? {
    readonly [k in keyof p]: k extends keyof i ? InvertPatternForExcludeInternal<p[k], i[k], empty> : InvertPattern<p[k]>;
} : Compute<{
    readonly [k in Exclude<keyof p, optKeys>]: k extends keyof i ? InvertPatternForExcludeInternal<p[k], i[k], empty> : InvertPattern<p[k]>;
} & {
    readonly [k in Cast<optKeys, keyof p>]?: k extends keyof i ? InvertPatternForExcludeInternal<p[k], i[k], empty> : InvertPattern<p[k]>;
}> : empty : empty : empty;
export {};
