import { useEffect, useMemo, useRef, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { createPortal } from 'react-dom';
import { apiClient, getApiErrorMessage } from '../../lib/apiClient';
import { TaskFormFields } from '../common/TaskFormFields';
import type { TaskFormData } from '../../lib/taskFormState';
import { buildTaskFormState, STATUS_LABEL } from '../../lib/taskFormState';
import { TaskMilestoneSection } from './TaskMilestoneSection';
import { TaskFeedbackSection } from './TaskFeedbackSection';
import type { FileRecord, Milestone, Task, TaskDetail, TeamMember } from '../../types';

type TaskWithRelations = Task & {
  milestones?: Milestone[];
  files?: FileRecord[];
  details?: TaskDetail[];
};
import { isProjectTask, isRoutineTask } from '../../lib/taskType';
import { projectFormToApiPayload, routineFormToApiPayload } from '../../lib/taskFormPayload';
import { invalidateTaskCaches } from '../../lib/taskQueryCache';
import { formatSectionDisplay } from '../../lib/sections';
import {
  BOARD_SLOTS,
  BOARD_SLOT_ORDER,
  getBoardSlot,
  resolveTaskBoardSlot,
  slotSectionLabel,
  type BoardSlotId,
} from '../../lib/boardLayout';
import { ROUTINE_CATEGORIES, getRoutineCategory } from '../../lib/routineCategories';
import '../../styles/task-manager.css';

type MainTab = 'project' | 'routine';

interface TaskManagerProps {
  tasks: Task[];
  sectionOptions: { value: string; label: string }[];
  quarter: string;
  teamMembers?: TeamMember[];
  onClose: () => void;
}

function fmtPeriod(task: Task): string {
  if (!task.startDate && !task.dueDate) return '';
  return `${task.startDate?.slice(0, 10) ?? '?'} ~ ${task.dueDate?.slice(0, 10) ?? '?'}`;
}

function slotClassForTask(task: Task): string {
  if (isRoutineTask(task.taskType)) return 'task-manager-row--routine';
  const slotId = resolveTaskBoardSlot(task);
  return slotId ? `task-manager-row--${slotId}` : '';
}

function matchesSearch(task: Task, query: string): boolean {
  if (!query.trim()) return true;
  const q = query.trim().toLowerCase();
  const hay = [
    task.title,
    task.description,
    task.detailDescription,
    task.category,
    task.section,
    task.issueNote,
  ]
    .filter(Boolean)
    .join(' ')
    .toLowerCase();
  return hay.includes(q);
}

function TaskManagerRow({
  task,
  variant,
  expanded,
  onToggle,
  sectionOptions,
  teamMembers,
  quarter,
  onSaved,
  onDeleted,
}: {
  task: Task;
  variant: MainTab;
  expanded: boolean;
  onToggle: () => void;
  sectionOptions: { value: string; label: string }[];
  teamMembers: TeamMember[];
  quarter: string;
  onSaved: () => void;
  onDeleted: () => void;
}) {
  const queryClient = useQueryClient();
  const rowRef = useRef<HTMLElement>(null);
  const [form, setForm] = useState<TaskFormData>(() =>
    buildTaskFormState({ task, variant, defaultQuarter: quarter }),
  );
  const [saving, setSaving] = useState(false);

  const { data: fullTask } = useQuery({
    queryKey: ['task', task.id],
    queryFn: async () => {
      const { data } = await apiClient.get<TaskWithRelations>(`/tasks/${task.id}`);
      return data;
    },
    enabled: expanded,
  });

  useEffect(() => {
    if (expanded) {
      setForm(buildTaskFormState({ task, variant, defaultQuarter: quarter }));
      requestAnimationFrame(() => {
        rowRef.current?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
      });
    }
  }, [expanded, task, variant, quarter]);

  const patch = useMutation({
    mutationFn: (data: Record<string, unknown>) => apiClient.patch(`/tasks/${task.id}`, data),
    onSuccess: () => invalidateTaskCaches(queryClient, task.id),
  });

  const remove = useMutation({
    mutationFn: () => apiClient.delete(`/tasks/${task.id}`),
    onSuccess: () => invalidateTaskCaches(queryClient, task.id),
  });

  const handleSave = async (e: React.FormEvent) => {
    e.preventDefault();
    setSaving(true);
    try {
      const payload =
        variant === 'project'
          ? projectFormToApiPayload({ ...form, taskType: '실행과제' })
          : routineFormToApiPayload({ ...form, taskType: '기반업무' });
      await patch.mutateAsync(payload);
      onSaved();
    } catch (err: unknown) {
      alert(getApiErrorMessage(err, '저장에 실패했습니다.'));
    } finally {
      setSaving(false);
    }
  };

  const handleDelete = async () => {
    if (!window.confirm(`"${task.title}" 업무를 삭제하시겠습니까?`)) return;
    try {
      await remove.mutateAsync();
      onDeleted();
    } catch (err: unknown) {
      alert(getApiErrorMessage(err, '삭제에 실패했습니다.'));
    }
  };

  const statusLabel = STATUS_LABEL[task.status] ?? task.status;
  const sectionLabel =
    variant === 'project'
      ? formatSectionDisplay(task.section)
      : getRoutineCategory(task) ?? task.category ?? '—';

  return (
    <article
      ref={rowRef}
      className={`task-manager-row ${slotClassForTask(task)}${expanded ? ' is-expanded' : ''}`}
    >
      <button type="button" className="task-manager-row__summary" onClick={onToggle}>
        <span className="task-manager-row__chevron" aria-hidden="true">
          ›
        </span>
        <span className="task-manager-row__title">{task.title}</span>
        <span className="task-manager-row__meta">
          <span
            className={`task-manager-badge ${variant === 'project' ? 'task-manager-badge--section' : 'task-manager-badge--category'}`}
          >
            {sectionLabel}
          </span>
          {variant === 'project' && (
            <span className="task-manager-badge task-manager-badge--progress">{task.progress}%</span>
          )}
          <span
            className={`task-manager-badge task-manager-badge--status${
              task.status === 'DONE' ? ' is-done' : task.status === 'IN_PROGRESS' ? ' is-active' : ''
            }`}
          >
            {statusLabel}
          </span>
          {variant === 'project' && fmtPeriod(task) && (
            <span className="task-manager-badge task-manager-badge--status">{fmtPeriod(task)}</span>
          )}
        </span>
      </button>

      {expanded && (
        <form className="task-manager-panel" onSubmit={handleSave}>
          <TaskFormFields
            variant={variant}
            form={form}
            onChange={setForm}
            sectionOptions={sectionOptions}
            teamMembers={teamMembers}
            idPrefix={`mgr-${task.id}`}
          />
          {fullTask && (
            <>
              <TaskMilestoneSection task={fullTask} variant={variant} teamMembers={teamMembers} />
              <TaskFeedbackSection
                taskId={task.id}
                milestones={fullTask.milestones ?? []}
                details={fullTask.details ?? []}
              />
            </>
          )}
          {!fullTask && <p className="task-form-empty">업무 일정·피드백 불러오는 중…</p>}
          <div className="task-manager-panel__actions">
            <button
              type="button"
              className="task-form-btn task-form-btn--danger"
              onClick={handleDelete}
              disabled={remove.isPending}
            >
              삭제
            </button>
            <button type="submit" className="task-form-btn task-form-btn--primary" disabled={saving}>
              {saving ? '저장 중…' : '저장'}
            </button>
          </div>
        </form>
      )}
    </article>
  );
}

function TaskManagerNewRow({
  variant,
  sectionOptions,
  teamMembers,
  quarter,
  defaultSection,
  onCreated,
  onCancel,
}: {
  variant: MainTab;
  sectionOptions: { value: string; label: string }[];
  teamMembers: TeamMember[];
  quarter: string;
  defaultSection: string;
  onCreated: () => void;
  onCancel: () => void;
}) {
  const queryClient = useQueryClient();
  const [form, setForm] = useState<TaskFormData>(() =>
    buildTaskFormState({
      variant,
      defaultQuarter: quarter,
      defaultSection,
      defaultCategory: ROUTINE_CATEGORIES[0],
    }),
  );
  const [saving, setSaving] = useState(false);

  const create = useMutation({
    mutationFn: (data: Record<string, unknown>) => apiClient.post('/tasks', data),
    onSuccess: () => invalidateTaskCaches(queryClient),
  });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setSaving(true);
    try {
      const payload = {
        ...(variant === 'project'
          ? projectFormToApiPayload({ ...form, taskType: '실행과제' })
          : routineFormToApiPayload({ ...form, taskType: '기반업무' })),
        priority: 'MEDIUM',
      };
      await create.mutateAsync(payload);
      onCreated();
    } catch (err: unknown) {
      alert(getApiErrorMessage(err, '추가에 실패했습니다.'));
    } finally {
      setSaving(false);
    }
  };

  return (
    <article className={`task-manager-row is-expanded ${variant === 'routine' ? 'task-manager-row--routine' : 'task-manager-row--hrm'}`}>
      <form className="task-manager-panel" style={{ paddingTop: 16 }} onSubmit={handleSubmit}>
        <TaskFormFields
          variant={variant}
          form={form}
          onChange={setForm}
          sectionOptions={sectionOptions}
          teamMembers={teamMembers}
          idPrefix="mgr-new"
        />
        <div className="task-manager-panel__actions">
          <button type="button" className="task-form-btn task-form-btn--ghost" onClick={onCancel}>
            취소
          </button>
          <button
            type="submit"
            className={`task-form-btn task-form-btn--primary${variant === 'routine' ? ' is-routine' : ''}`}
            disabled={saving}
          >
            {saving ? '추가 중…' : '추가'}
          </button>
        </div>
      </form>
    </article>
  );
}

export function TaskManager({ tasks, sectionOptions, quarter, teamMembers = [], onClose }: TaskManagerProps) {
  const [mainTab, setMainTab] = useState<MainTab>('project');
  const [filterKey, setFilterKey] = useState<string>('전체');
  const [search, setSearch] = useState('');
  const [expandedId, setExpandedId] = useState<string | null>(null);
  const [adding, setAdding] = useState(false);

  const projectTasks = useMemo(
    () => tasks.filter((t) => isProjectTask(t.taskType) && matchesSearch(t, search)),
    [tasks, search],
  );
  const routineTasks = useMemo(
    () => tasks.filter((t) => isRoutineTask(t.taskType) && matchesSearch(t, search)),
    [tasks, search],
  );

  const projectFilters = useMemo(
    () => [
      { key: '전체', label: '전체' },
      ...BOARD_SLOTS.map((slot) => ({
        key: slot.id,
        label: slot.defaultTitle,
      })),
    ],
    [],
  );

  const routineFilters = useMemo(
    () => [{ key: '전체', label: '전체' }, ...ROUTINE_CATEGORIES.map((cat) => ({ key: cat, label: cat }))],
    [],
  );

  const filteredProjects = useMemo(() => {
    if (filterKey === '전체') return projectTasks;
    if (!BOARD_SLOT_ORDER.includes(filterKey as BoardSlotId)) return projectTasks;
    const slot = getBoardSlot(filterKey as BoardSlotId);
    return projectTasks.filter((t) => resolveTaskBoardSlot(t) === slot.id);
  }, [projectTasks, filterKey]);

  const filteredRoutines = useMemo(() => {
    if (filterKey === '전체') return routineTasks;
    return routineTasks.filter((t) => getRoutineCategory(t) === filterKey);
  }, [routineTasks, filterKey]);

  const visibleTasks = mainTab === 'project' ? filteredProjects : filteredRoutines;
  const filters = mainTab === 'project' ? projectFilters : routineFilters;

  const defaultSection =
    filterKey !== '전체' && mainTab === 'project'
      ? slotSectionLabel(getBoardSlot(filterKey as BoardSlotId))
      : sectionOptions[0]?.value ?? '인사관리';

  const switchTab = (tab: MainTab) => {
    setMainTab(tab);
    setFilterKey('전체');
    setExpandedId(null);
    setAdding(false);
  };

  return createPortal(
    <div className="task-manager-overlay" onClick={onClose}>
      <div className="task-manager-shell" onClick={(e) => e.stopPropagation()}>
        <header className="task-manager-header">
          <div>
            <h2 className="task-manager-header__title">업무관리</h2>
            <p className="task-manager-header__quarter">{quarter}</p>
          </div>
          <button type="button" className="task-manager-close" onClick={onClose} aria-label="닫기">
            ✕
          </button>
        </header>

        <div className="task-manager-toolbar">
          <div className="task-manager-tabs">
            <button
              type="button"
              className={`task-manager-tab${mainTab === 'project' ? ' is-active' : ''}`}
              onClick={() => switchTab('project')}
            >
              프로젝트
            </button>
            <button
              type="button"
              className={`task-manager-tab is-routine${mainTab === 'routine' ? ' is-active' : ''}`}
              onClick={() => switchTab('routine')}
            >
              상시업무
            </button>
          </div>

          <div className="task-manager-filters">
            {filters.map((f) => (
              <button
                key={f.key}
                type="button"
                className={`task-manager-chip${filterKey === f.key ? ' is-active' : ''}`}
                onClick={() => {
                  setFilterKey(f.key);
                  setExpandedId(null);
                }}
              >
                {f.label}
              </button>
            ))}
          </div>

          <div className="task-manager-toolbar__spacer" />

          <input
            type="search"
            className="task-manager-search"
            placeholder="제목·개요 검색"
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />

          <button
            type="button"
            className="task-manager-add"
            onClick={() => {
              setAdding(true);
              setExpandedId(null);
            }}
          >
            + {mainTab === 'project' ? '프로젝트' : '상시업무'} 추가
          </button>
        </div>

        <div className="task-manager-list">
          {adding && (
            <TaskManagerNewRow
              variant={mainTab}
              sectionOptions={sectionOptions}
              teamMembers={teamMembers}
              quarter={quarter}
              defaultSection={defaultSection}
              onCreated={() => setAdding(false)}
              onCancel={() => setAdding(false)}
            />
          )}

          {visibleTasks.length === 0 && !adding ? (
            <p className="task-manager-empty">표시할 업무가 없습니다.</p>
          ) : (
            visibleTasks.map((task) => (
              <TaskManagerRow
                key={task.id}
                task={task}
                variant={mainTab}
                expanded={expandedId === task.id}
                onToggle={() => setExpandedId((id) => (id === task.id ? null : task.id))}
                sectionOptions={sectionOptions}
                teamMembers={teamMembers}
                quarter={quarter}
                onSaved={() => setExpandedId(null)}
                onDeleted={() => setExpandedId(null)}
              />
            ))
          )}
        </div>

        <footer className="task-manager-footer">
          <span>
            프로젝트 <strong>{projectTasks.length}</strong>건
          </span>
          <span>
            상시업무 <strong>{routineTasks.length}</strong>건
          </span>
          <span>
            현재 목록 <strong>{visibleTasks.length}</strong>건
          </span>
        </footer>
      </div>
    </div>,
    document.body,
  );
}
