import { create } from "zustand";
import { apiFetch } from "../lib/api";

/**
 * Apple-Style Device-Approval Store.
 *
 * Hält 2 Flows getrennt:
 *
 * 1. **outgoing** — Das AKTUELLE Gerät ist das NEUE Gerät und wartet auf
 *    Approval. UI: Modal mit Code + Spinner + "Per Email senden".
 *
 * 2. **incoming** — Das AKTUELLE Gerät ist ein EXISTIERENDES Gerät und kriegt
 *    eine Approval-Request push (realtime). UI: Sheet mit Code + Device-Picker
 *    + [Erlauben] / [Ablehnen].
 *
 * Realtime: hooks/useDeviceApprovalRealtime.ts subscribet auf
 * rebreak.device_approval_requests filtered by user_id und ruft
 * setIncoming() / refresh().
 */

export type DeviceApprovalRecord = {
  id: string;
  userId: string;
  newDeviceId: string;
  newPlatform: string;
  newModel: string | null;
  newName: string | null;
  newOsVersion: string | null;
  code: string;
  status: "pending" | "approved" | "rejected" | "expired";
  approvedByDeviceRowId: string | null;
  approvedAt: string | null;
  rejectedAt: string | null;
  evictedDeviceRowId: string | null;
  emailSentAt: string | null;
  createdAt: string;
  expiresAt: string;
};

type State = {
  // Outgoing (this device is new, waiting for approval)
  outgoing: DeviceApprovalRecord | null;
  outgoingError: string | null;
  outgoingEmailSent: boolean;
  outgoingLoading: boolean;

  // Incoming (this device is existing, must approve/reject)
  incoming: DeviceApprovalRecord | null;

  // Actions — outgoing
  requestApproval: (deviceInfo: {
    deviceId: string;
    platform: string;
    model?: string | null;
    name?: string | null;
    osVersion?: string | null;
  }) => Promise<DeviceApprovalRecord | null>;
  pollOutgoing: () => Promise<void>;
  sendEmailFallback: () => Promise<void>;
  clearOutgoing: () => void;

  // Actions — incoming
  setIncoming: (a: DeviceApprovalRecord | null) => void;
  approveIncoming: (evictDeviceRowId: string | null) => Promise<void>;
  rejectIncoming: () => Promise<void>;
  refreshIncomingFromServer: () => Promise<void>;
};

export const useDeviceApprovalStore = create<State>((set, get) => ({
  outgoing: null,
  outgoingError: null,
  outgoingEmailSent: false,
  outgoingLoading: false,
  incoming: null,

  async requestApproval(deviceInfo) {
    set({ outgoingLoading: true, outgoingError: null });
    try {
      const { approval } = await apiFetch<{ approval: DeviceApprovalRecord }>(
        "/api/devices/approvals",
        {
          method: "POST",
          body: deviceInfo,
          skipDeviceHeader: true,
        }
      );
      set({ outgoing: approval, outgoingLoading: false });
      return approval;
    } catch (err: any) {
      set({
        outgoingError: err?.message ?? "Fehler beim Anfordern",
        outgoingLoading: false,
      });
      return null;
    }
  },

  async pollOutgoing() {
    const cur = get().outgoing;
    if (!cur || cur.status !== "pending") return;
    try {
      const { approval } = await apiFetch<{ approval: DeviceApprovalRecord }>(
        `/api/devices/approvals/${cur.id}`,
        { skipDeviceHeader: true }
      );
      set({ outgoing: approval });
    } catch {
      // Network error → just retry next tick
    }
  },

  async sendEmailFallback() {
    const cur = get().outgoing;
    if (!cur) return;
    set({ outgoingError: null });
    try {
      const { approval, alreadySent } = await apiFetch<{
        approval: DeviceApprovalRecord;
        alreadySent: boolean;
      }>(`/api/devices/approvals/${cur.id}/email`, {
        method: "POST",
        skipDeviceHeader: true,
      });
      set({ outgoing: approval, outgoingEmailSent: true });
      if (alreadySent) {
        // schon einmal raus — User informieren
      }
    } catch (err: any) {
      set({ outgoingError: err?.message ?? "E-Mail-Versand fehlgeschlagen" });
    }
  },

  clearOutgoing() {
    set({
      outgoing: null,
      outgoingError: null,
      outgoingEmailSent: false,
      outgoingLoading: false,
    });
  },

  setIncoming(a) {
    set({ incoming: a });
  },

  async approveIncoming(evictDeviceRowId) {
    const cur = get().incoming;
    if (!cur) return;
    await apiFetch(`/api/devices/approvals/${cur.id}/approve`, {
      method: "POST",
      body: { evictDeviceRowId },
    });
    set({ incoming: null });
  },

  async rejectIncoming() {
    const cur = get().incoming;
    if (!cur) return;
    await apiFetch(`/api/devices/approvals/${cur.id}/reject`, {
      method: "POST",
    });
    set({ incoming: null });
  },

  async refreshIncomingFromServer() {
    try {
      const { approvals } = await apiFetch<{ approvals: DeviceApprovalRecord[] }>(
        "/api/devices/approvals"
      );
      // Show the newest one
      const newest = approvals.find((a) => a.status === "pending") ?? null;
      // Nur setzen wenn keine andere gerade angezeigt wird ODER newer als die aktuelle
      const cur = get().incoming;
      if (!cur || (newest && newest.id !== cur.id)) {
        set({ incoming: newest });
      }
    } catch {
      // ignore
    }
  },
}));
