/**
 * Unified draft hook for CreateTeamDialog form state.
 *
 * Persists team name, members, paths, and flags to IndexedDB so that
 * navigating away from the Teams tab and back preserves user input.
 *
 * Key guarantees:
 * - Single IndexedDB key (`createTeamDraft:form`), no TTL.
 * - Race-safe: late async load never overwrites fresh user input.
 * - Debounced writes with immediate flush on unmount.
 * - Draft is cleared only on successful team creation.
 *
 * Pattern mirrors `useComposerDraft.ts`.
 */

import { useCallback, useEffect, useRef, useState } from 'react';

import { createMemberDraft } from '@renderer/components/team/members/membersEditorUtils';
import {
  type CreateTeamDraftSnapshot,
  createTeamDraftStorage,
  type SerializedMemberDraft,
} from '@renderer/services/createTeamDraftStorage';

import type { MemberDraft } from '@renderer/components/team/members/membersEditorTypes';

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export interface UseCreateTeamDraftResult {
  teamName: string;
  setTeamName: (v: string) => void;
  members: MemberDraft[];
  setMembers: (v: MemberDraft[]) => void;
  cwdMode: 'project' | 'custom';
  setCwdMode: (v: 'project' | 'custom') => void;
  selectedProjectPath: string;
  setSelectedProjectPath: (v: string) => void;
  customCwd: string;
  setCustomCwd: (v: string) => void;
  soloTeam: boolean;
  setSoloTeam: (v: boolean) => void;
  launchTeam: boolean;
  setLaunchTeam: (v: boolean) => void;
  teamColor: string;
  setTeamColor: (v: string) => void;

  /** `true` after the initial IndexedDB load completes. */
  isLoaded: boolean;
  /** Clear all draft state and delete the IndexedDB entry. */
  clearDraft: () => void;
}

// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------

const DEBOUNCE_MS = 400;

// ---------------------------------------------------------------------------
// Serialization helpers
// ---------------------------------------------------------------------------

function serializeMembers(members: MemberDraft[]): SerializedMemberDraft[] {
  return members.map(({ id, name, roleSelection, customRole, workflow }) => ({
    id,
    name,
    roleSelection,
    customRole,
    workflow,
  }));
}

function deserializeMembers(serialized: SerializedMemberDraft[]): MemberDraft[] {
  return serialized.map((m) =>
    createMemberDraft({
      id: m.id,
      name: m.name,
      roleSelection: m.roleSelection,
      customRole: m.customRole,
      workflow: m.workflow,
    })
  );
}

// ---------------------------------------------------------------------------
// Hook
// ---------------------------------------------------------------------------

export function useCreateTeamDraft(): UseCreateTeamDraftResult {
  // ── State ──────────────────────────────────────────────────────────────
  const [teamName, setTeamNameState] = useState('');
  const [members, setMembersState] = useState<MemberDraft[]>([]);
  const [cwdMode, setCwdModeState] = useState<'project' | 'custom'>('project');
  const [selectedProjectPath, setSelectedProjectPathState] = useState('');
  const [customCwd, setCustomCwdState] = useState('');
  const [soloTeam, setSoloTeamState] = useState(false);
  const [launchTeam, setLaunchTeamState] = useState(true);
  const [teamColor, setTeamColorState] = useState('');
  const [isLoaded, setIsLoaded] = useState(false);

  // ── Refs (latest values for debounced callbacks) ───────────────────────
  const teamNameRef = useRef('');
  const membersRef = useRef<MemberDraft[]>([]);
  const cwdModeRef = useRef<'project' | 'custom'>('project');
  const selectedProjectPathRef = useRef('');
  const customCwdRef = useRef('');
  const soloTeamRef = useRef(false);
  const launchTeamRef = useRef(true);
  const teamColorRef = useRef('');
  const mountedRef = useRef(true);
  const userTouchedRef = useRef(false);
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const pendingRef = useRef<CreateTeamDraftSnapshot | null>(null);

  useEffect(() => {
    mountedRef.current = true;
    return () => {
      mountedRef.current = false;
    };
  }, []);

  // ── Snapshot builder ───────────────────────────────────────────────────

  const buildSnapshot = useCallback((): CreateTeamDraftSnapshot => {
    return {
      version: 1,
      teamName: teamNameRef.current,
      members: serializeMembers(membersRef.current),
      cwdMode: cwdModeRef.current,
      selectedProjectPath: selectedProjectPathRef.current,
      customCwd: customCwdRef.current,
      soloTeam: soloTeamRef.current,
      launchTeam: launchTeamRef.current,
      teamColor: teamColorRef.current,
      updatedAt: Date.now(),
    };
  }, []);

  // ── Flush / schedule ───────────────────────────────────────────────────

  const flushPending = useCallback(() => {
    if (timerRef.current != null) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
    if (pendingRef.current != null) {
      const pending = pendingRef.current;
      pendingRef.current = null;
      const isEmpty = pending.teamName === '' && pending.members.length === 0;
      if (isEmpty) {
        void createTeamDraftStorage.deleteSnapshot();
      } else {
        void createTeamDraftStorage.saveSnapshot(pending);
      }
    }
  }, []);

  const scheduleSave = useCallback(() => {
    const snapshot = buildSnapshot();
    pendingRef.current = snapshot;

    if (timerRef.current != null) {
      clearTimeout(timerRef.current);
    }

    timerRef.current = setTimeout(() => {
      timerRef.current = null;
      const pending = pendingRef.current;
      pendingRef.current = null;
      if (pending == null) return;

      const isEmpty = pending.teamName === '' && pending.members.length === 0;
      if (isEmpty) {
        void createTeamDraftStorage.deleteSnapshot();
      } else {
        void createTeamDraftStorage.saveSnapshot(pending);
      }
    }, DEBOUNCE_MS);
  }, [buildSnapshot]);

  // ── Apply snapshot to state ────────────────────────────────────────────

  const applySnapshot = useCallback((snap: CreateTeamDraftSnapshot) => {
    const deserialized = deserializeMembers(snap.members);

    teamNameRef.current = snap.teamName;
    membersRef.current = deserialized;
    cwdModeRef.current = snap.cwdMode;
    selectedProjectPathRef.current = snap.selectedProjectPath;
    customCwdRef.current = snap.customCwd;
    soloTeamRef.current = snap.soloTeam;
    launchTeamRef.current = snap.launchTeam;
    teamColorRef.current = snap.teamColor;

    setTeamNameState(snap.teamName);
    setMembersState(deserialized);
    setCwdModeState(snap.cwdMode);
    setSelectedProjectPathState(snap.selectedProjectPath);
    setCustomCwdState(snap.customCwd);
    setSoloTeamState(snap.soloTeam);
    setLaunchTeamState(snap.launchTeam);
    setTeamColorState(snap.teamColor);
  }, []);

  // ── Load on mount ──────────────────────────────────────────────────────

  useEffect(() => {
    let cancelled = false;

    void (async () => {
      const snapshot = await createTeamDraftStorage.loadSnapshot();
      if (cancelled) return;

      // Race protection: if user already interacted, don't overwrite
      if (userTouchedRef.current) {
        if (mountedRef.current) setIsLoaded(true);
        return;
      }

      if (snapshot != null) {
        applySnapshot(snapshot);
      }

      if (mountedRef.current) setIsLoaded(true);
    })();

    return () => {
      cancelled = true;
    };
  }, [applySnapshot]);

  // Flush on unmount
  useEffect(() => {
    return () => {
      flushPending();
    };
  }, [flushPending]);

  // ── Setters ────────────────────────────────────────────────────────────

  const setTeamName = useCallback(
    (v: string) => {
      userTouchedRef.current = true;
      teamNameRef.current = v;
      setTeamNameState(v);
      scheduleSave();
    },
    [scheduleSave]
  );

  const setMembers = useCallback(
    (v: MemberDraft[]) => {
      userTouchedRef.current = true;
      membersRef.current = v;
      setMembersState(v);
      scheduleSave();
    },
    [scheduleSave]
  );

  const setCwdMode = useCallback(
    (v: 'project' | 'custom') => {
      userTouchedRef.current = true;
      cwdModeRef.current = v;
      setCwdModeState(v);
      scheduleSave();
    },
    [scheduleSave]
  );

  const setSelectedProjectPath = useCallback(
    (v: string) => {
      userTouchedRef.current = true;
      selectedProjectPathRef.current = v;
      setSelectedProjectPathState(v);
      scheduleSave();
    },
    [scheduleSave]
  );

  const setCustomCwd = useCallback(
    (v: string) => {
      userTouchedRef.current = true;
      customCwdRef.current = v;
      setCustomCwdState(v);
      scheduleSave();
    },
    [scheduleSave]
  );

  const setSoloTeam = useCallback(
    (v: boolean) => {
      userTouchedRef.current = true;
      soloTeamRef.current = v;
      setSoloTeamState(v);
      scheduleSave();
    },
    [scheduleSave]
  );

  const setLaunchTeam = useCallback(
    (v: boolean) => {
      userTouchedRef.current = true;
      launchTeamRef.current = v;
      setLaunchTeamState(v);
      scheduleSave();
    },
    [scheduleSave]
  );

  const setTeamColor = useCallback(
    (v: string) => {
      userTouchedRef.current = true;
      teamColorRef.current = v;
      setTeamColorState(v);
      scheduleSave();
    },
    [scheduleSave]
  );

  // ── Clear all ──────────────────────────────────────────────────────────

  const clearDraft = useCallback(() => {
    if (timerRef.current != null) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
    pendingRef.current = null;
    // Keep userTouchedRef true so a late IDB load (theoretically impossible
    // since isLoaded gates submit, but defensive) cannot resurrect deleted data.
    userTouchedRef.current = true;

    teamNameRef.current = '';
    membersRef.current = [];
    cwdModeRef.current = 'project';
    selectedProjectPathRef.current = '';
    customCwdRef.current = '';
    soloTeamRef.current = false;
    launchTeamRef.current = true;
    teamColorRef.current = '';

    setTeamNameState('');
    setMembersState([]);
    setCwdModeState('project');
    setSelectedProjectPathState('');
    setCustomCwdState('');
    setSoloTeamState(false);
    setLaunchTeamState(true);
    setTeamColorState('');

    void createTeamDraftStorage.deleteSnapshot();
  }, []);

  return {
    teamName,
    setTeamName,
    members,
    setMembers,
    cwdMode,
    setCwdMode,
    selectedProjectPath,
    setSelectedProjectPath,
    customCwd,
    setCustomCwd,
    soloTeam,
    setSoloTeam,
    launchTeam,
    setLaunchTeam,
    teamColor,
    setTeamColor,
    isLoaded,
    clearDraft,
  };
}
