import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import {
  createFrameEntry,
  deleteFrameEntry,
  listFrameEntries,
  updateFrameEntry,
} from '@/shared/api/frame';
import { FRAME_QUERY_KEYS } from '@/shared/constants/frame';
import { FrameSectionKey } from '@/shared/types/frame';
import {
  EditableFrameEntry,
  FrameEntryDraft,
  FrameEntryViewModel,
} from '@/business/frame/types';
import {
  toFrameEntryMutationDto,
  toFrameEntryViewModel,
} from '@/business/frame/mappers';
import { canEditFrameEntries } from '@/business/frame/selectors';
import { UserRole } from '@/shared/types/app';
import { mapApiListRows } from '@/shared/business/apiListRows';
import { useInvalidatingMutation } from '@/shared/business/queryMutations';

const EMPTY_FRAME_ENTRIES: readonly FrameEntryViewModel[] = [];

function createEmptyDraft(author: string): FrameEntryDraft {
  return {
    weekOf: '',
    postedDate: new Date().toLocaleDateString('en-US', {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
    }),
    formal: '',
    recognition: '',
    application: '',
    management: '',
    emotional: '',
    author,
  };
}

function isValidDraft(entry: EditableFrameEntry): boolean {
  return Boolean(
    entry.weekOf.trim()
    && entry.postedDate.trim()
    && entry.formal.trim()
    && entry.recognition.trim()
    && entry.application.trim()
    && entry.management.trim()
    && entry.emotional.trim()
    && entry.author.trim(),
  );
}

export function useFrameEntries() {
  return useQuery({
    queryKey: FRAME_QUERY_KEYS.entries,
    queryFn: () => mapApiListRows(listFrameEntries(), toFrameEntryViewModel),
  });
}

export function useFrameModule(userRole: UserRole, userName: string) {
  const canEdit = canEditFrameEntries(userRole);
  const authorName = userName.trim();
  const [expandedIdState, setExpandedIdState] = useState<string | null>(null);
  const [isEditing, setIsEditing] = useState(false);
  const [editEntry, setEditEntry] = useState<FrameEntryViewModel | null>(null);
  const [showNewForm, setShowNewForm] = useState(false);
  const [newEntry, setNewEntry] = useState<FrameEntryDraft>(() => createEmptyDraft(authorName));
  const [formError, setFormError] = useState<string | null>(null);

  const entriesQuery = useFrameEntries();

  const createMutation = useInvalidatingMutation({
    mutationFn: (entry: EditableFrameEntry) => createFrameEntry(toFrameEntryMutationDto(entry)),
    invalidateQueryKey: FRAME_QUERY_KEYS.entries,
    onSuccess: (createdEntry) => {
      setExpandedIdState(createdEntry.id);
      setShowNewForm(false);
      setNewEntry(createEmptyDraft(authorName));
      setFormError(null);
    },
  });

  const updateMutation = useInvalidatingMutation({
    mutationFn: (entry: FrameEntryViewModel) => updateFrameEntry(entry.id, toFrameEntryMutationDto(entry)),
    invalidateQueryKey: FRAME_QUERY_KEYS.entries,
    onSuccess: (updatedEntry) => {
      setExpandedIdState(updatedEntry.id);
      setIsEditing(false);
      setEditEntry(null);
      setFormError(null);
    },
  });

  const deleteMutation = useInvalidatingMutation({
    mutationFn: (id: string) => deleteFrameEntry(id),
    invalidateQueryKey: FRAME_QUERY_KEYS.entries,
    onSuccess: () => {
      setExpandedIdState(null);
      setIsEditing(false);
      setEditEntry(null);
      setFormError(null);
    },
  });

  const entries = entriesQuery.data ?? EMPTY_FRAME_ENTRIES;
  const expandedId = expandedIdState === null ? (entries[0]?.id || '') : expandedIdState;

  function updateNewEntryField(key: keyof FrameEntryDraft, value: string) {
    setNewEntry((current) => ({ ...current, [key]: value }));
  }

  function updateNewEntrySection(key: FrameSectionKey, value: string) {
    setNewEntry((current) => ({ ...current, [key]: value }));
  }

  function updateEditEntrySection(key: FrameSectionKey, value: string) {
    setEditEntry((current) => current ? { ...current, [key]: value } : current);
  }

  function startEditing(entry: FrameEntryViewModel) {
    setIsEditing(true);
    setEditEntry(entry);
    setFormError(null);
  }

  function cancelEditing() {
    setIsEditing(false);
    setEditEntry(null);
    setFormError(null);
  }

  async function saveNewEntry() {
    if (!isValidDraft(newEntry)) {
      setFormError('Complete every F.R.A.M.E. field before publishing.');
      return;
    }

    await createMutation.mutateAsync(newEntry);
  }

  async function saveEditEntry() {
    if (!editEntry) {
      return;
    }

    if (!isValidDraft(editEntry)) {
      setFormError('Complete every F.R.A.M.E. field before saving.');
      return;
    }

    await updateMutation.mutateAsync(editEntry);
  }

  async function deleteEntry(id: string) {
    await deleteMutation.mutateAsync(id);
  }

  return {
    entries,
    expandedId,
    isEditing,
    editEntry,
    showNewForm,
    newEntry,
    formError,
    canEdit,
    isLoading: entriesQuery.isLoading,
    isRefreshing: entriesQuery.isFetching,
    isSaving: createMutation.isPending || updateMutation.isPending,
    isDeleting: deleteMutation.isPending,
    error: entriesQuery.error || createMutation.error || updateMutation.error || deleteMutation.error,
    setExpandedId: setExpandedIdState,
    setShowNewForm,
    updateNewEntryField,
    updateNewEntrySection,
    updateEditEntrySection,
    startEditing,
    cancelEditing,
    saveNewEntry,
    saveEditEntry,
    deleteEntry,
    refresh: entriesQuery.refetch,
  };
}
