import type { FastifyInstance } from 'fastify';
import { authenticate, requireRole } from '../middleware/auth.js';
import { companyService } from '../services/companyService.js';
import { authService } from '../services/authService.js';
import { auditService } from '../services/auditService.js';
import { ticketService } from '../services/ticketService.js';
import { knowledgeModuleService } from '../services/knowledgeModuleService.js';
import { aiAgentService } from '../services/aiAgentService.js';

const staff = [authenticate, requireRole('admin', 'user')];

export async function companyRoutes(fastify: FastifyInstance) {
  fastify.get('/', { preHandler: staff }, async (_req, reply) => {
    return reply.send(await companyService.list());
  });

  fastify.post('/', { preHandler: staff }, async (req, reply) => {
    const { name } = req.body as { name: string };
    if (!name?.trim()) return reply.status(400).send({ error: 'name is required' });
    try {
      const c = await companyService.create(name);
      await auditService.log(req.user!.sub, 'user', 'company.created', 'company', c.id, { name: c.name });
      return reply.status(201).send(c);
    } catch (e: unknown) {
      const err = e as { statusCode?: number; message?: string };
      return reply.status(err.statusCode ?? 500).send({ error: err.message ?? 'Failed to create company' });
    }
  });

  fastify.get('/:id/knowledge-modules', { preHandler: staff }, async (req, reply) => {
    const { id } = req.params as { id: string };
    const company = await companyService.getById(id);
    if (!company) return reply.status(404).send({ error: 'Company not found' });
    return reply.send(await knowledgeModuleService.listForCompany(id));
  });

  fastify.put('/:id/default-ai-agent', { preHandler: staff }, async (req, reply) => {
    const { id } = req.params as { id: string };
    const company = await companyService.getById(id);
    if (!company) return reply.status(404).send({ error: 'Company not found' });
    const body = req.body as { ai_agent_id?: string | null };
    if (!('ai_agent_id' in body)) {
      return reply.status(400).send({ error: 'ai_agent_id is required (null to clear)' });
    }
    try {
      await aiAgentService.setCompanyDefaultAgent(id, body.ai_agent_id ?? null);
    } catch (e: unknown) {
      const err = e as { statusCode?: number; message?: string };
      return reply.status(err.statusCode ?? 500).send({ error: err.message ?? 'Failed to set agent' });
    }
    await auditService.log(req.user!.sub, 'user', 'company.default_ai_agent', 'company', id, {
      ai_agent_id: body.ai_agent_id,
    });
    const aid = await aiAgentService.getCompanyDefaultAgentId(id);
    const default_ai_agent = aid ? await aiAgentService.getById(aid) : null;
    return reply.send({ default_ai_agent });
  });

  fastify.put('/:id/knowledge-modules', { preHandler: staff }, async (req, reply) => {
    const { id } = req.params as { id: string };
    const company = await companyService.getById(id);
    if (!company) return reply.status(404).send({ error: 'Company not found' });
    const { module_ids } = req.body as { module_ids?: string[] };
    if (!Array.isArray(module_ids)) {
      return reply.status(400).send({ error: 'module_ids array is required' });
    }
    await knowledgeModuleService.setCompanyModules(id, module_ids);
    await auditService.log(req.user!.sub, 'user', 'company.knowledge_modules_set', 'company', id, {
      count: module_ids.length,
    });
    return reply.send(await knowledgeModuleService.listForCompany(id));
  });

  fastify.get('/:id', { preHandler: staff }, async (req, reply) => {
    const { id } = req.params as { id: string };
    const company = await companyService.getById(id);
    if (!company) return reply.status(404).send({ error: 'Company not found' });
    const aggregates = await companyService.getDetailAggregates(id);
    const tickets = await ticketService.list({ companyId: id, limit: 200, offset: 0 });
    const aid = await aiAgentService.getCompanyDefaultAgentId(id);
    const default_ai_agent = aid ? await aiAgentService.getById(aid) : null;
    return reply.send({ ...company, ...aggregates, tickets, default_ai_agent });
  });

  fastify.patch('/:id', { preHandler: staff }, async (req, reply) => {
    const { id } = req.params as { id: string };
    const body = req.body as { name?: string; ai_autoreply_enabled?: boolean };
    const hasName = typeof body.name === 'string' && body.name.trim().length > 0;
    const hasAi = typeof body.ai_autoreply_enabled === 'boolean';
    if (!hasName && !hasAi) {
      return reply.status(400).send({ error: 'name and/or ai_autoreply_enabled is required' });
    }
    let c = await companyService.getById(id);
    if (!c) return reply.status(404).send({ error: 'Company not found' });
    if (hasName) {
      const updated = await companyService.updateName(id, body.name!);
      if (!updated) return reply.status(404).send({ error: 'Company not found' });
      c = updated;
      await auditService.log(req.user!.sub, 'user', 'company.updated', 'company', id, { name: body.name });
    }
    if (hasAi) {
      const updated = await companyService.updateAiAutoreply(id, body.ai_autoreply_enabled!);
      if (!updated) return reply.status(404).send({ error: 'Company not found' });
      c = updated;
      await auditService.log(req.user!.sub, 'user', 'company.ai_autoreply', 'company', id, {
        ai_autoreply_enabled: body.ai_autoreply_enabled,
      });
    }
    return reply.send(c);
  });

  fastify.post('/:id/users', { preHandler: staff }, async (req, reply) => {
    const { id } = req.params as { id: string };
    const { email, password, display_name } = req.body as {
      email: string;
      password: string;
      display_name?: string | null;
    };
    if (!email || !password) {
      return reply.status(400).send({ error: 'email and password are required' });
    }
    const company = await companyService.getById(id);
    if (!company) return reply.status(404).send({ error: 'Company not found' });
    try {
      const user = await authService.createCompanyPortalUser(email, password, id, display_name);
      await auditService.log(req.user!.sub, 'user', 'company.portal_user_created', 'user', user.id, {
        email,
        companyId: id,
      });
      return reply.status(201).send(user);
    } catch (e: unknown) {
      const err = e as { message?: string };
      return reply.status(409).send({ error: err.message ?? 'Conflict' });
    }
  });
}
