import { Router } from 'express';
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import { Booking, JobCard, JobTask, Service, TaskImage, User, Vehicle } from '../models/index.js';
import { requireAuth, requireRole } from '../middleware/auth.js';
import { sendError } from '../util/httpError.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const uploadDir = path.join(__dirname, '../../uploads');

const router = Router();

if (!fs.existsSync(uploadDir)) {
  fs.mkdirSync(uploadDir, { recursive: true });
}

const storage = multer.diskStorage({
  destination: (_req, _file, cb) => cb(null, uploadDir),
  filename: (_req, file, cb) => {
    const safe = `${Date.now()}-${file.originalname.replace(/[^a-zA-Z0-9._-]/g, '_')}`;
    cb(null, safe);
  },
});
const upload = multer({ storage, limits: { fileSize: 5 * 1024 * 1024 } });

const taskInclude = [
  { model: Service, as: 'service', attributes: ['name'] },
  {
    model: JobCard,
    as: 'job_card',
    attributes: ['id'],
    include: [
      {
        model: Booking,
        as: 'booking',
        include: [{ model: Vehicle, as: 'vehicle', attributes: ['brand', 'model', 'number_plate'] }],
      },
    ],
  },
];

function mapTask(t) {
  return {
    ...t.toJSON(),
    service_name: t.service?.name ?? null,
    job_card_id: t.job_card?.id ?? null,
    vehicle_brand: t.job_card?.booking?.vehicle?.brand ?? null,
    vehicle_model: t.job_card?.booking?.vehicle?.model ?? null,
    number_plate: t.job_card?.booking?.vehicle?.number_plate ?? null,
    sub_tasks: t.sub_tasks ?? [],
  };
}

router.get('/', requireAuth, async (req, res) => {
  if (req.user.role === 'admin') {
    const rows = await JobTask.findAll({
      include: taskInclude,
      order: [['id', 'DESC']],
    });
    return res.json({ tasks: rows.map(mapTask) });
  }
  if (req.user.role === 'employee') {
    const rows = await JobTask.findAll({
      where: { employee_id: req.user.id },
      include: taskInclude,
      order: [['id', 'DESC']],
    });
    return res.json({ tasks: rows.map(mapTask) });
  }
  return sendError(res, 403, 'FORBIDDEN', 'Role cannot list tasks');
});

router.get('/:id', requireAuth, async (req, res) => {
  const id = Number(req.params.id);
  const task = await JobTask.findByPk(id, { include: taskInclude });
  if (!task) {
    return sendError(res, 404, 'NOT_FOUND', 'Task not found');
  }
  if (req.user.role === 'admin') {
    return res.json({ task });
  }
  if (req.user.role === 'employee' && Number(task.employee_id) === req.user.id) {
    return res.json({ task: mapTask(task) });
  }
  return sendError(res, 403, 'FORBIDDEN', 'Cannot view this task');
});

router.patch('/:id', requireAuth, async (req, res) => {
  const id = Number(req.params.id);
  const { status, sub_tasks } = req.body;
  
  const task = await JobTask.findByPk(id);
  if (!task) {
    return sendError(res, 404, 'NOT_FOUND', 'Task not found');
  }
  
  if (req.user.role === 'employee') {
    if (Number(task.employee_id) !== req.user.id) {
      return sendError(res, 403, 'FORBIDDEN', 'Task not assigned to you');
    }
  } else if (req.user.role !== 'admin') {
    return sendError(res, 403, 'FORBIDDEN', 'Cannot update task');
  }

  if (status) {
    const allowed = ['pending', 'in_progress', 'completed'];
    if (!allowed.includes(status)) {
      return sendError(res, 400, 'VALIDATION_ERROR', 'Invalid task status');
    }
    task.status = status;
  }

  if (sub_tasks !== undefined) {
    if (!Array.isArray(sub_tasks)) {
      return sendError(res, 400, 'VALIDATION_ERROR', 'sub_tasks must be an array');
    }
    task.sub_tasks = sub_tasks;
  }

  await task.save();
  const out = await JobTask.findByPk(id, { include: taskInclude });
  return res.json({ task: mapTask(out) });
});

router.patch('/:id/assign', requireAuth, requireRole('admin', 'super_admin'), async (req, res) => {
  const id = Number(req.params.id);
  const employee_id = Number(req.body?.employee_id);
  if (!employee_id) {
    return sendError(res, 400, 'VALIDATION_ERROR', 'employee_id required');
  }
  const emp = await User.findOne({ where: { id: employee_id, role: 'employee' } });
  if (!emp) {
    return sendError(res, 400, 'VALIDATION_ERROR', 'Invalid employee');
  }
  const task = await JobTask.findByPk(id);
  if (!task) {
    return sendError(res, 404, 'NOT_FOUND', 'Task not found');
  }
  task.employee_id = employee_id;
  await task.save();
  const out = await JobTask.findByPk(id, { include: taskInclude });
  return res.json({ task: mapTask(out) });
});

router.post(
  '/:id/images',
  requireAuth,
  upload.single('image'),
  async (req, res) => {
    const id = Number(req.params.id);
    if (!req.file) {
      return sendError(res, 400, 'VALIDATION_ERROR', 'image file required');
    }
    const task = await JobTask.findByPk(id);
    if (!task) {
      return sendError(res, 404, 'NOT_FOUND', 'Task not found');
    }
    if (req.user.role === 'employee' && Number(task.employee_id) !== req.user.id) {
      return sendError(res, 403, 'FORBIDDEN', 'Task not assigned to you');
    }
    if (req.user.role !== 'admin' && req.user.role !== 'employee') {
      return sendError(res, 403, 'FORBIDDEN', 'Cannot upload');
    }
    const image_url = `/uploads/${req.file.filename}`;
    const ins = await TaskImage.create({ job_task_id: id, image_url });
    return res.status(201).json({
      image: { id: Number(ins.id), image_url },
    });
  }
);

export default router;
