import { useEffect, useState } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { apiClient, getApiErrorMessage } from '../../lib/apiClient';
import { StageFormFields } from '../common/StageFormFields';
import { buildStageFormState, stageFormToApiPayload } from '../../lib/stageFormState';
import type { StageFormData } from '../detail/stageFormTypes';
import { invalidateTaskCaches } from '../../lib/taskQueryCache';
import { fmtMilestonePeriodSummary } from '../../lib/milestonePeriods';
import {
  StageModal,
  type StageFileSavePayload,
} from '../detail/StageModal';
import { sortFilesByOrder } from '../../lib/fileDisplay';
import type { FileRecord, Milestone, TaskDetail, TeamMember } from '../../types';

type TaskWithRelations = {
  id: string;
  milestones?: Milestone[];
  files?: FileRecord[];
  details?: TaskDetail[];
};

function MilestoneRow({
  taskId,
  milestone,
  variant,
  teamMembers,
  expanded,
  onToggle,
  onOpenFiles,
}: {
  taskId: string;
  milestone: Milestone;
  variant: 'project' | 'routine';
  teamMembers: TeamMember[];
  expanded: boolean;
  onToggle: () => void;
  onOpenFiles: () => void;
}) {
  const queryClient = useQueryClient();
  const [form, setForm] = useState<StageFormData>(() => buildStageFormState(milestone, variant));
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    if (expanded) {
      setForm(buildStageFormState(milestone, variant));
    }
  }, [expanded, milestone, variant]);

  const save = async (e: React.FormEvent) => {
    e.preventDefault();
    setSaving(true);
    try {
      await apiClient.patch(`/milestones/item/${milestone.id}`, stageFormToApiPayload(form, variant));
      invalidateTaskCaches(queryClient, taskId);
    } catch (err: unknown) {
      alert(getApiErrorMessage(err, '업무 일정 저장에 실패했습니다.'));
    } finally {
      setSaving(false);
    }
  };

  const remove = async () => {
    if (!window.confirm(`"${milestone.title}" 일정을 삭제하시겠습니까?`)) return;
    try {
      await apiClient.delete(`/milestones/item/${milestone.id}`);
      invalidateTaskCaches(queryClient, taskId);
    } catch (err: unknown) {
      alert(getApiErrorMessage(err, '삭제에 실패했습니다.'));
    }
  };

  const periodSummary = fmtMilestonePeriodSummary(milestone);

  return (
    <article className={`task-manager-subrow${expanded ? ' is-expanded' : ''}`}>
      <button type="button" className="task-manager-subrow__head" onClick={onToggle}>
        <span className="task-manager-row__chevron" aria-hidden="true">
          ›
        </span>
        <span className="task-manager-subrow__title">{milestone.title}</span>
        <span className="task-manager-subrow__meta">
          {periodSummary && <span className="task-manager-badge task-manager-badge--status">{periodSummary}</span>}
          <span className="task-manager-badge task-manager-badge--progress">{milestone.progress}%</span>
        </span>
      </button>
      {expanded && (
        <form className="task-manager-subpanel" onSubmit={save}>
          <StageFormFields
            variant={variant}
            form={form}
            onChange={setForm}
            teamMembers={teamMembers}
            idPrefix={`ms-${milestone.id}`}
          />
          <div className="task-manager-panel__actions">
            <button type="button" className="task-form-btn task-form-btn--ghost" onClick={onOpenFiles}>
              첨부 파일 편집
            </button>
            <button type="button" className="task-form-btn task-form-btn--danger" onClick={remove}>
              일정 삭제
            </button>
            <button type="submit" className="task-form-btn task-form-btn--primary" disabled={saving}>
              {saving ? '저장 중…' : '일정 저장'}
            </button>
          </div>
        </form>
      )}
    </article>
  );
}

function NewMilestoneForm({
  taskId,
  variant,
  teamMembers,
  onCreated,
  onCancel,
}: {
  taskId: string;
  variant: 'project' | 'routine';
  teamMembers: TeamMember[];
  onCreated: () => void;
  onCancel: () => void;
}) {
  const queryClient = useQueryClient();
  const [form, setForm] = useState<StageFormData>(() => buildStageFormState(undefined, variant));
  const [saving, setSaving] = useState(false);

  const submit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!form.title.trim()) return;
    setSaving(true);
    try {
      await apiClient.post(`/milestones/${taskId}`, stageFormToApiPayload(form, variant));
      invalidateTaskCaches(queryClient, taskId);
      onCreated();
    } catch (err: unknown) {
      alert(getApiErrorMessage(err, '업무 일정 추가에 실패했습니다.'));
    } finally {
      setSaving(false);
    }
  };

  return (
    <form className="task-manager-subpanel task-manager-subpanel--new" onSubmit={submit}>
      <StageFormFields
        variant={variant}
        form={form}
        onChange={setForm}
        teamMembers={teamMembers}
        idPrefix="ms-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" disabled={saving}>
          {saving ? '추가 중…' : '일정 추가'}
        </button>
      </div>
    </form>
  );
}

export function TaskMilestoneSection({
  task,
  variant,
  teamMembers,
}: {
  task: TaskWithRelations;
  variant: 'project' | 'routine';
  teamMembers: TeamMember[];
}) {
  const queryClient = useQueryClient();
  const milestones = task.milestones ?? [];
  const files = task.files ?? [];
  const [expandedId, setExpandedId] = useState<string | null>(null);
  const [adding, setAdding] = useState(false);
  const [fileModalMs, setFileModalMs] = useState<Milestone | null>(null);
  const [fileSaving, setFileSaving] = useState(false);

  const uploadFiles = async (milestoneId: string, filePayload: StageFileSavePayload['uploads']) => {
    for (const item of filePayload) {
      const form = new FormData();
      form.append('file', item.file);
      form.append('milestoneId', milestoneId);
      form.append('sortOrder', String(item.sortOrder));
      if (item.displayName.trim()) {
        form.append('displayName', item.displayName.trim());
      }
      await apiClient.post(`/files/upload/${task.id}`, form);
    }
  };

  const handleFileSave = async (data: StageFormData, filePayload: StageFileSavePayload) => {
    if (!fileModalMs) return;
    setFileSaving(true);
    try {
      await apiClient.patch(`/milestones/item/${fileModalMs.id}`, stageFormToApiPayload(data, variant));
      for (const id of filePayload.deletedFileIds) {
        await apiClient.delete(`/files/${id}`);
      }
      for (const rep of filePayload.replacements) {
        const form = new FormData();
        form.append('file', rep.file);
        await apiClient.post(`/files/${rep.id}/replace`, form);
      }
      for (const edit of filePayload.existingEdits) {
        const original = files.find((f) => f.id === edit.id);
        if (!original) continue;
        const prevName = (original.displayName ?? '').trim();
        const nextName = edit.displayName.trim();
        const prevOrder = original.sortOrder ?? 0;
        if (nextName !== prevName || edit.sortOrder !== prevOrder) {
          await apiClient.patch(`/files/${edit.id}`, {
            displayName: nextName || null,
            sortOrder: edit.sortOrder,
          });
        }
      }
      if (filePayload.uploads.length > 0) {
        await uploadFiles(fileModalMs.id, filePayload.uploads);
      }
      invalidateTaskCaches(queryClient, task.id);
      setFileModalMs(null);
    } catch (err: unknown) {
      alert(getApiErrorMessage(err, '첨부 파일 저장에 실패했습니다.'));
    } finally {
      setFileSaving(false);
    }
  };

  return (
    <section className="task-manager-section">
      <div className="task-manager-section__head">
        <h4 className="task-manager-section__title">업무 일정</h4>
        <button
          type="button"
          className="task-form-link-btn"
          onClick={() => {
            setAdding(true);
            setExpandedId(null);
          }}
        >
          + 일정 추가
        </button>
      </div>

      {adding && (
        <NewMilestoneForm
          taskId={task.id}
          variant={variant}
          teamMembers={teamMembers}
          onCreated={() => setAdding(false)}
          onCancel={() => setAdding(false)}
        />
      )}

      {milestones.length === 0 && !adding ? (
        <p className="task-form-empty">등록된 업무 일정이 없습니다.</p>
      ) : (
        milestones.map((ms) => (
          <MilestoneRow
            key={ms.id}
            taskId={task.id}
            milestone={ms}
            variant={variant}
            teamMembers={teamMembers}
            expanded={expandedId === ms.id}
            onToggle={() => setExpandedId((id) => (id === ms.id ? null : ms.id))}
            onOpenFiles={() => setFileModalMs(ms)}
          />
        ))
      )}

      {fileModalMs && (
        <StageModal
          mode="edit"
          variant={variant}
          milestone={fileModalMs}
          existingFiles={sortFilesByOrder(files.filter((f) => f.milestoneId === fileModalMs.id))}
          teamMembers={teamMembers}
          saving={fileSaving}
          onClose={() => setFileModalMs(null)}
          onSave={handleFileSave}
        />
      )}
    </section>
  );
}
