import { Router } from 'express';
import type { Server } from 'socket.io';
import { prisma } from '../lib/prisma';
import { resolveCreatorId } from '../lib/resolveUser';
import { AppError } from '../middleware/errorHandler';
import { emitTaskListRefresh, emitTaskUpdated } from '../socket';
import {
  formatTask,
  parseMemberIds,
  syncTaskMembers,
  taskDetailInclude,
  taskInclude,
} from '../lib/taskQuery';
import { deriveIssueFields, normalizeIssueEntries } from '../lib/taskIssues';

const router = Router();

function resolveIssuePayload(body: Record<string, any>) {
  if (body.issueEntries !== undefined) {
    const entries = normalizeIssueEntries(body.issueEntries);
    return deriveIssueFields(entries);
  }
  if (body.issueNote !== undefined) {
    const text = typeof body.issueNote === 'string' ? body.issueNote.trim() : '';
    if (!text) {
      return { issueEntries: [], issueNote: null, showIssue: false };
    }
    return deriveIssueFields([{ id: 'legacy', text, showOnCard: body.showIssue !== false }]);
  }
  return null;
}

// GET /api/tasks  — 목록 조회 (필터: status, quarter, assigneeId)
router.get('/', async (req, res, next) => {
  try {
    const { status, quarter, assigneeId, category } = req.query as Record<string, string>;

    const tasks = await prisma.task.findMany({
      where: {
        ...(status && { status: status as any }),
        ...(quarter && { quarter }),
        ...(assigneeId && { assigneeId }),
        ...(category && { category }),
      },
      include: taskInclude,
      orderBy: { updatedAt: 'desc' },
    });

    res.json(tasks.map((t) => formatTask(t)));
  } catch (err) {
    next(err);
  }
});

// GET /api/tasks/:id  — 단건 상세 조회
router.get('/:id', async (req, res, next) => {
  try {
    const taskId = String(req.params.id);
    const task = await prisma.task.findUnique({
      where: { id: taskId },
      include: taskDetailInclude,
    });

    if (!task) throw new AppError(404, '업무를 찾을 수 없습니다.');
    res.json(formatTask(task));
  } catch (err) {
    next(err);
  }
});

// POST /api/tasks  — 업무 등록
router.post('/', async (req, res, next) => {
  try {
    const body = req.body as Record<string, any>;
    const { title, description, detailDescription, status, priority, quarter, category,
            section, tag, taskType, progress, issueNote, startDate, dueDate, assigneeId, showDate,
            showDescription, showStatus, showIssue, showProgress, pmMemberId } = body;

    if (!title || !quarter) {
      throw new AppError(400, '제목과 분기는 필수입니다.');
    }

    const creatorId = await resolveCreatorId(body.creatorId);
    const assigneeMemberIds = parseMemberIds(body);
    const issuePayload = resolveIssuePayload(body);

    const task = await prisma.task.create({
      data: {
        title,
        description,
        detailDescription: detailDescription ?? null,
        status: (status as any) || 'TODO',
        priority: (priority as any) || 'MEDIUM',
        quarter,
        category,
        section,
        tag,
        taskType,
        progress: progress ? Number(progress) : 0,
        issueNote: issuePayload?.issueNote ?? (issueNote || null),
        issueEntries: issuePayload?.issueEntries as any ?? undefined,
        startDate: startDate ? new Date(startDate) : undefined,
        dueDate: dueDate ? new Date(dueDate) : undefined,
        showDate: showDate !== undefined ? showDate === 'true' || showDate === true : true,
        showDescription: showDescription !== undefined ? showDescription === 'true' || showDescription === true : true,
        showStatus: showStatus !== undefined ? showStatus === 'true' || showStatus === true : true,
        showIssue: issuePayload?.showIssue ?? (showIssue !== undefined ? showIssue === 'true' || showIssue === true : true),
        showProgress: showProgress !== undefined ? showProgress === 'true' || showProgress === true : true,
        assigneeId: assigneeId || null,
        pmMemberId: pmMemberId || null,
        creatorId,
      },
      include: taskInclude,
    });

    if (assigneeMemberIds !== undefined) {
      await syncTaskMembers(task.id, undefined, assigneeMemberIds);
      const refreshed = await prisma.task.findUnique({
        where: { id: task.id },
        include: taskInclude,
      });
      res.status(201).json(formatTask(refreshed!));
      return;
    }

    res.status(201).json(formatTask(task));
  } catch (err) {
    next(err);
  }
});

// PATCH /api/tasks/:id  — 업무 수정
router.patch('/:id', async (req, res, next) => {
  try {
    const existing = await prisma.task.findUnique({ where: { id: req.params.id } });
    if (!existing) throw new AppError(404, '업무를 찾을 수 없습니다.');

    const body = req.body as Record<string, any>;
    const { title, description, detailDescription, status, priority, quarter, category,
            section, tag, taskType, progress, issueNote, startDate, dueDate, assigneeId, showDate,
            showDescription, showStatus, showIssue, showProgress, pmMemberId } = body;

    const assigneeMemberIds = parseMemberIds(body);
    const issuePayload = resolveIssuePayload(body);

    await prisma.task.update({
      where: { id: req.params.id },
      data: {
        ...(title && { title }),
        ...(description !== undefined && { description }),
        ...(detailDescription !== undefined && { detailDescription: detailDescription || null }),
        ...(status && { status: status as any }),
        ...(priority && { priority: priority as any }),
        ...(quarter && { quarter }),
        ...(category !== undefined && { category }),
        ...(section !== undefined && { section }),
        ...(tag !== undefined && { tag }),
        ...(taskType !== undefined && { taskType }),
        ...(progress !== undefined && { progress: Number(progress) }),
        ...(issuePayload
          ? {
              issueEntries: issuePayload.issueEntries as any,
              issueNote: issuePayload.issueNote,
              showIssue: issuePayload.showIssue,
            }
          : issueNote !== undefined
            ? {
                issueNote: issueNote || null,
                ...(issueNote
                  ? {}
                  : { issueEntries: [] as any, showIssue: false }),
              }
            : {}),
        ...(startDate !== undefined && { startDate: startDate ? new Date(startDate) : null }),
        ...(dueDate !== undefined && { dueDate: dueDate ? new Date(dueDate) : null }),
        ...(assigneeId !== undefined && { assigneeId: assigneeId || null }),
        ...(pmMemberId !== undefined && { pmMemberId: pmMemberId || null }),
        ...(showDate !== undefined && { showDate: showDate === true || showDate === 'true' }),
        ...(showDescription !== undefined && { showDescription: showDescription === true || showDescription === 'true' }),
        ...(showStatus !== undefined && { showStatus: showStatus === true || showStatus === 'true' }),
        ...(showIssue !== undefined && { showIssue: showIssue === true || showIssue === 'true' }),
        ...(showProgress !== undefined && { showProgress: showProgress === true || showProgress === 'true' }),
      },
    });

    if (pmMemberId !== undefined || assigneeMemberIds !== undefined) {
      await syncTaskMembers(
        req.params.id,
        pmMemberId !== undefined ? (pmMemberId || null) : undefined,
        assigneeMemberIds,
      );
    }

    const task = await prisma.task.findUnique({
      where: { id: req.params.id },
      include: taskInclude,
    });

    const formatted = formatTask(task!);
    const io = req.app.get('io') as Server | undefined;
    if (io) {
      emitTaskUpdated(io, req.params.id, formatted);
      emitTaskListRefresh(io);
    }

    res.json(formatted);
  } catch (err) {
    next(err);
  }
});

// DELETE /api/tasks/:id  — 업무 삭제
router.delete('/:id', async (req, res, next) => {
  try {
    const existing = await prisma.task.findUnique({ where: { id: req.params.id } });
    if (!existing) throw new AppError(404, '업무를 찾을 수 없습니다.');

    await prisma.task.delete({ where: { id: req.params.id } });
    res.status(204).send();
  } catch (err) {
    next(err);
  }
});

export default router;
