"use client";

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from "react";
import type { Recipient } from "@/types";
import { delay, generateId } from "@/lib/mockApi";

const STORAGE_KEY = "xremit_recipients";

const SEED: Recipient[] = [
  {
    id: "rcp_001",
    name: "Rahim Uddin",
    countryCode: "BD",
    method: "bank",
    relationship: "family",
    bank: {
      bankName: "Dutch-Bangla Bank",
      accountNumber: "1234567890123",
      iban: "BD33DBBL0000001234567890123",
    },
    lastSentAt: new Date(Date.now() - 86_400_000).toISOString(),
    createdAt: new Date(Date.now() - 86_400_000 * 60).toISOString(),
  },
  {
    id: "rcp_002",
    name: "Priya Sharma",
    countryCode: "IN",
    method: "mobile",
    relationship: "friend",
    mobile: { phone: "+91 98765 43210" },
    lastSentAt: new Date(Date.now() - 86_400_000 * 7).toISOString(),
    createdAt: new Date(Date.now() - 86_400_000 * 90).toISOString(),
  },
  {
    id: "rcp_003",
    name: "Carlos Mendoza",
    countryCode: "MX",
    method: "cash",
    relationship: "business",
    cash: { pickupLocation: "Elektra — Centro Histórico, Ciudad de México" },
    lastSentAt: new Date(Date.now() - 86_400_000 * 14).toISOString(),
    createdAt: new Date(Date.now() - 86_400_000 * 120).toISOString(),
  },
];

interface RecipientsContextValue {
  recipients: Recipient[];
  hydrated: boolean;
  loading: boolean;
  getById: (id: string) => Recipient | undefined;
  add: (input: Omit<Recipient, "id" | "createdAt">) => Promise<Recipient>;
  update: (id: string, patch: Partial<Recipient>) => Promise<Recipient>;
  remove: (id: string) => Promise<void>;
  touchLastSent: (id: string) => void;
}

const RecipientsContext = createContext<RecipientsContextValue | undefined>(undefined);

function read(): Recipient[] {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) return JSON.parse(raw) as Recipient[];
    localStorage.setItem(STORAGE_KEY, JSON.stringify(SEED));
    return SEED;
  } catch {
    return SEED;
  }
}

function persist(list: Recipient[]) {
  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(list));
  } catch {
    /* ignore */
  }
}

export function RecipientsProvider({ children }: { children: React.ReactNode }) {
  const [recipients, setRecipients] = useState<Recipient[]>([]);
  const [hydrated, setHydrated] = useState(false);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    setRecipients(read());
    setHydrated(true);
  }, []);

  const getById = useCallback(
    (id: string) => recipients.find((r) => r.id === id),
    [recipients],
  );

  const add = useCallback(
    async (input: Omit<Recipient, "id" | "createdAt">): Promise<Recipient> => {
      setLoading(true);
      await delay();
      const next: Recipient = {
        ...input,
        id: generateId("rcp"),
        createdAt: new Date().toISOString(),
      };
      setRecipients((prev) => {
        const updated = [next, ...prev];
        persist(updated);
        return updated;
      });
      setLoading(false);
      return next;
    },
    [],
  );

  const update = useCallback(
    async (id: string, patch: Partial<Recipient>): Promise<Recipient> => {
      setLoading(true);
      await delay();
      let updated: Recipient | undefined;
      setRecipients((prev) => {
        const list = prev.map((r) => {
          if (r.id === id) {
            updated = { ...r, ...patch };
            return updated;
          }
          return r;
        });
        persist(list);
        return list;
      });
      setLoading(false);
      if (!updated) throw new Error("Recipient not found");
      return updated;
    },
    [],
  );

  const remove = useCallback(async (id: string) => {
    setLoading(true);
    await delay();
    setRecipients((prev) => {
      const list = prev.filter((r) => r.id !== id);
      persist(list);
      return list;
    });
    setLoading(false);
  }, []);

  const touchLastSent = useCallback((id: string) => {
    setRecipients((prev) => {
      const list = prev.map((r) =>
        r.id === id ? { ...r, lastSentAt: new Date().toISOString() } : r,
      );
      persist(list);
      return list;
    });
  }, []);

  const value = useMemo<RecipientsContextValue>(
    () => ({ recipients, hydrated, loading, getById, add, update, remove, touchLastSent }),
    [recipients, hydrated, loading, getById, add, update, remove, touchLastSent],
  );

  return <RecipientsContext.Provider value={value}>{children}</RecipientsContext.Provider>;
}

export function useRecipients() {
  const ctx = useContext(RecipientsContext);
  if (!ctx) throw new Error("useRecipients must be used within RecipientsProvider");
  return ctx;
}
