import { useCallback, useEffect, useState } from 'react';
import { apiFetch } from '../lib/api';

export type DomainStatus = 'active' | 'submitted' | 'approved' | 'rejected';

export type EntryKind = 'web' | 'mail_domain' | 'mail_display_name';

export type CustomDomain = {
  id: string;
  domain: string;
  type?: EntryKind;
  status: DomainStatus;
  addedAt?: string;
  postId?: string | null;
  submission?: { id: string; yesVotes: number; noVotes: number; status: string } | null;
};

export type Plan = 'free' | 'pro' | 'legend';

export type Tier = {
  plan: Plan;
  domainLimit: number;            // free=5, pro=5, legend=10
  refillEnabled: boolean;          // free=false, pro/legend=true
  globalBlocklist: boolean;        // free=false, pro/legend=true
  canSubmit: boolean;              // free=false, pro/legend=true
  usedSlots: number;               // active+submitted (NICHT approved/rejected)
  atLimit: boolean;
};

function deriveTier(plan: Plan, domains: CustomDomain[]): Tier {
  const limit = plan === 'legend' ? 10 : 5;
  const refill = plan !== 'free';
  const usedSlots = domains.filter((d) => d.status === 'active' || d.status === 'submitted').length;
  return {
    plan,
    domainLimit: limit,
    refillEnabled: refill,
    globalBlocklist: refill,
    canSubmit: refill,
    usedSlots,
    atLimit: usedSlots >= limit,
  };
}

export type CountsByType = {
  web: number;
  mail: number;
};

export type LimitsByType = {
  web: number;
  mail: number;
};

export type UseCustomDomainsReturn = {
  domains: CustomDomain[];
  tier: Tier;
  countsByType: CountsByType;
  limits: LimitsByType;
  loading: boolean;
  error: string | null;
  refresh: () => Promise<void>;
  addDomain: (pattern: string, kind?: 'web' | 'mail') => Promise<{ ok: boolean; error?: string; alreadyGlobal?: boolean }>;
  submitDomain: (id: string) => Promise<{ ok: boolean; error?: string }>;
  removeDomain: (id: string) => Promise<{ ok: boolean; error?: string }>;
  /** Live-Validate (regex) ob string gültiger Domain-Name ist. */
  isValidDomain: (s: string) => boolean;
  /** Normalize: lowercase, http(s)://, /path stripping, www. weg. */
  normalizeDomain: (s: string) => string;
};

const DOMAIN_REGEX = /^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i;

export function normalizeDomain(input: string): string {
  let s = input.trim().toLowerCase();
  if (s.startsWith('https://')) s = s.slice(8);
  else if (s.startsWith('http://')) s = s.slice(7);
  const slash = s.indexOf('/');
  if (slash >= 0) s = s.slice(0, slash);
  if (s.startsWith('www.')) s = s.slice(4);
  return s;
}

export function isValidDomain(input: string): boolean {
  const n = normalizeDomain(input);
  if (!n || n.length > 253) return false;
  return DOMAIN_REGEX.test(n);
}

/**
 * Custom-Domain CRUD gegen `/api/custom-domains/*` mit Tier-aware Limits.
 *
 * Tier-Logik (Single-Source-of-Truth: User.plan):
 *   Free   → 5 Slots, kein Refill, keine Submit
 *   Pro    → 5 Slots, Refill bei approved/rejected, Submit erlaubt
 *   Legend → 10 Slots, Refill, Submit
 */
export function useCustomDomains(plan: Plan): UseCustomDomainsReturn {
  const [domains, setDomains] = useState<CustomDomain[]>([]);
  const [apiCounts, setApiCounts] = useState<CountsByType | null>(null);
  const [apiLimits, setApiLimits] = useState<LimitsByType | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchDomains = useCallback(async () => {
    try {
      // Backend `GET /api/custom-domains` returns
      //   { items: CustomDomain[], counts: { web, mail }, limits: { web, mail } }
      // since the slot-pool split (commit f2b81ee). Legacy fall-throughs cover
      // an older shape (bare array or { domains }) in case a cached client
      // ever hits this code path before the deploy lands.
      const res = await apiFetch<
        | CustomDomain[]
        | { domains?: CustomDomain[] }
        | { items?: CustomDomain[]; counts?: CountsByType; limits?: LimitsByType }
      >('/api/custom-domains');
      let arr: CustomDomain[] = [];
      let counts: CountsByType | null = null;
      let limits: LimitsByType | null = null;
      if (Array.isArray(res)) {
        arr = res;
      } else if (res) {
        arr = (res as any).items ?? (res as any).domains ?? [];
        counts = (res as any).counts ?? null;
        limits = (res as any).limits ?? null;
      }
      setDomains(arr);
      setApiCounts(counts);
      setApiLimits(limits);
      setError(null);
    } catch (e: any) {
      console.error('[useCustomDomains] fetch failed:', e?.message ?? e);
      setError(e?.message ?? 'unknown');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchDomains();
  }, [fetchDomains]);

  const addDomain = useCallback(
    async (input: string, kind?: 'web' | 'mail') => {
      const resolvedKind: 'web' | 'mail' = kind ?? (input.includes('@') ? 'mail' : 'web');
      if (resolvedKind === 'web' && !isValidDomain(input)) return { ok: false, error: 'invalid_domain' };
      if (resolvedKind === 'mail' && !input.trim()) return { ok: false, error: 'invalid_pattern' };
      const tier = deriveTier(plan, domains);
      if (tier.atLimit) return { ok: false, error: 'limit_reached' };
      const pattern = resolvedKind === 'web' ? normalizeDomain(input) : input.trim();
      const body: Record<string, string> = { pattern };
      if (kind !== undefined) body.kind = kind;
      try {
        const res = await apiFetch<any>('/api/custom-domains', {
          method: 'POST',
          body,
        });
        if (res?.alreadyGlobal) {
          return { ok: false, alreadyGlobal: true };
        }
        await fetchDomains();
        return { ok: true };
      } catch (e: any) {
        return { ok: false, error: e?.message ?? 'add_failed' };
      }
    },
    [plan, domains, fetchDomains],
  );

  const submitDomain = useCallback(
    async (id: string) => {
      const tier = deriveTier(plan, domains);
      if (!tier.canSubmit) return { ok: false, error: 'plan_does_not_support_submit' };
      try {
        await apiFetch(`/api/custom-domains/${id}/submit`, { method: 'POST', body: {} });
        await fetchDomains();
        return { ok: true };
      } catch (e: any) {
        return { ok: false, error: e?.message ?? 'submit_failed' };
      }
    },
    [plan, domains, fetchDomains],
  );

  const removeDomain = useCallback(
    async (id: string) => {
      try {
        await apiFetch(`/api/custom-domains/${id}`, { method: 'DELETE' });
        await fetchDomains();
        return { ok: true };
      } catch (e: any) {
        return { ok: false, error: e?.message ?? 'remove_failed' };
      }
    },
    [fetchDomains],
  );

  const tier = deriveTier(plan, domains);

  // Prefer API-driven counts/limits when the backend returned the new shape;
  // fall back to local derivation so the UI works during a stale-bundle moment.
  const countsByType: CountsByType =
    apiCounts ?? {
      web: domains.filter(
        (d) => d.status !== 'approved' && (d.type === 'web' || !d.type),
      ).length,
      mail: domains.filter(
        (d) => d.status !== 'approved' && d.type === 'mail_domain',
      ).length,
    };
  const limits: LimitsByType =
    apiLimits ?? {
      web: plan === 'legend' ? 10 : 5,
      mail: plan === 'legend' ? 10 : 5,
    };

  return {
    domains,
    tier,
    countsByType,
    limits,
    loading,
    error,
    refresh: fetchDomains,
    addDomain,
    submitDomain,
    removeDomain,
    isValidDomain,
    normalizeDomain,
  };
}
