// src/server/features/reference_books/local_it.routes.ts
// HTTP handlers for local IT equipment routes (Admin Only)

import { FastifyPluginAsync } from 'fastify';
import { ZodTypeProvider } from 'fastify-type-provider-zod';
import { z } from 'zod';
import { localITService, localSecurityService, otherEquipmentService } from './local_it.service';
import { AppError } from '@serverShared/lib/errors';
import { requireAuth, type UserInfo } from '@serverShared/lib/auth';
import { AppPermission } from '@shared/contracts/permissions';
import {
  createLocalITSchema,
  updateLocalITSchema,
  createLocalSecuritySchema,
  updateLocalSecuritySchema,
  createOtherEquipmentSchema,
  updateOtherEquipmentSchema,
  localITResponseSchema,
  localSecurityResponseSchema,
  otherEquipmentResponseSchema,
} from './local_it.schema';

const localITRoutes: FastifyPluginAsync = async (fastify, opts) => {
  const server = fastify.withTypeProvider<ZodTypeProvider>();

  // ============ LOCAL IT ROUTES ============

  // Create local IT entry (ADMIN ONLY)
  server.post('/local-it', {
    preHandler: requireAuth(),
    onRequest: fastify.canAny(AppPermission.EQUIPMENT_EDIT, AppPermission.EQUIPMENT_REQUEST_APPROVAL),
    schema: {
      body: createLocalITSchema,
      response: {
        201: localITResponseSchema,
      },
    },
    handler: async (request: any) => {
      const result = await localITService.create(request.body, request.user as UserInfo);
      return result;
    },
  });

  // Get all local IT entries (ADMIN ONLY)
  server.get('/local-it', {
    preHandler: requireAuth(),
    onRequest: fastify.can(AppPermission.EQUIPMENT_READ),
    schema: {
      query: z.object({
        archived: z.enum(['true', 'false']).optional(),
      }),
      response: {
        200: z.array(localITResponseSchema),
      },
    },
    handler: async (request: any) => {
      const { archived } = request.query;
      
      // TODO: Implement archived filter if needed
      return await localITService.findAll();
    },
  });

  // Get local IT entry by ID (ADMIN ONLY)
  server.get('/local-it/:id', {
    preHandler: requireAuth(),
    onRequest: fastify.can(AppPermission.EQUIPMENT_READ),
    schema: {
      params: z.object({ id: z.string() }),
      response: {
        200: localITResponseSchema,
        404: z.object({
          success: z.literal(false),
          error: z.object({
            message: z.string(),
            code: z.string(),
          }),
        }),
      },
    },
    handler: async (request: any) => {
      const { id } = request.params;
      const entry = await localITService.findById(id);
      
      if (!entry) {
        throw new AppError('Local IT entry not found', 404, 'NOT_FOUND');
      }
      
      return entry;
    },
  });

  // Update local IT entry (ADMIN ONLY)
  server.put('/local-it/:id', {
    preHandler: requireAuth(),
    onRequest: fastify.canAny(AppPermission.EQUIPMENT_EDIT, AppPermission.EQUIPMENT_REQUEST_APPROVAL),
    schema: {
      params: z.object({ id: z.string() }),
      body: updateLocalITSchema,
      response: {
        200: localITResponseSchema,
        404: z.object({
          success: z.literal(false),
          error: z.object({
            message: z.string(),
            code: z.string(),
          }),
        }),
      },
    },
    handler: async (request: any) => {
      const { id } = request.params;
      const updated = await localITService.update(id, request.body, request.user as UserInfo);
      
      if (!updated) {
        throw new AppError('Local IT entry not found', 404, 'NOT_FOUND');
      }
      
      return updated;
    },
  });

  // Delete (archive) local IT entry (ADMIN ONLY)
  server.delete('/local-it/:id', {
    preHandler: requireAuth(),
    onRequest: fastify.can(AppPermission.EQUIPMENT_EDIT),
    schema: {
      params: z.object({ id: z.string() }),
      response: {
        200: z.object({
          success: z.literal(true),
          message: z.string(),
        }),
        404: z.object({
          success: z.literal(false),
          error: z.object({
            message: z.string(),
            code: z.string(),
          }),
        }),
      },
    },
    handler: async (request: any) => {
      const { id } = request.params;
      
      const exists = await localITService.findById(id);
      if (!exists) {
        throw new AppError('Local IT entry not found', 404, 'NOT_FOUND');
      }
      
      await localITService.softDelete(id, request.user as UserInfo);
      
      return {
        success: true as const,
        message: 'Local IT entry archived',
      };
    },
  });

  // ============ LOCAL SECURITY ROUTES ============

  // Create local security entry (ADMIN ONLY)
  server.post('/local-security', {
    preHandler: requireAuth(),
    onRequest: fastify.canAny(AppPermission.EQUIPMENT_EDIT, AppPermission.EQUIPMENT_REQUEST_APPROVAL),
    schema: {
      body: createLocalSecuritySchema,
      response: {
        201: localSecurityResponseSchema,
      },
    },
    handler: async (request: any) => {
      const result = await localSecurityService.create(request.body, request.user as UserInfo);
      return result;
    },
  });

  // Get all local security entries (ADMIN ONLY)
  server.get('/local-security', {
    preHandler: requireAuth(),
    onRequest: fastify.can(AppPermission.EQUIPMENT_READ),
    schema: {
      query: z.object({
        archived: z.enum(['true', 'false']).optional(),
      }),
      response: {
        200: z.array(localSecurityResponseSchema),
      },
    },
    handler: async (request: any) => {
      const { archived } = request.query;
      
      // TODO: Implement archived filter if needed
      return await localSecurityService.findAll();
    },
  });

  // Get local security entry by ID (ADMIN ONLY)
  server.get('/local-security/:id', {
    preHandler: requireAuth(),
    onRequest: fastify.can(AppPermission.EQUIPMENT_READ),
    schema: {
      params: z.object({ id: z.string() }),
      response: {
        200: localSecurityResponseSchema,
        404: z.object({
          success: z.literal(false),
          error: z.object({
            message: z.string(),
            code: z.string(),
          }),
        }),
      },
    },
    handler: async (request: any) => {
      const { id } = request.params;
      const entry = await localSecurityService.findById(id);
      
      if (!entry) {
        throw new AppError('Local security entry not found', 404, 'NOT_FOUND');
      }
      
      return entry;
    },
  });

  // Update local security entry (ADMIN ONLY)
  server.put('/local-security/:id', {
    preHandler: requireAuth(),
    onRequest: fastify.canAny(AppPermission.EQUIPMENT_EDIT, AppPermission.EQUIPMENT_REQUEST_APPROVAL),
    schema: {
      params: z.object({ id: z.string() }),
      body: updateLocalSecuritySchema,
      response: {
        200: localSecurityResponseSchema,
        404: z.object({
          success: z.literal(false),
          error: z.object({
            message: z.string(),
            code: z.string(),
          }),
        }),
      },
    },
    handler: async (request: any) => {
      const { id } = request.params;
      const updated = await localSecurityService.update(id, request.body, request.user as UserInfo);
      
      if (!updated) {
        throw new AppError('Local security entry not found', 404, 'NOT_FOUND');
      }
      
      return updated;
    },
  });

  // Delete (archive) local security entry (ADMIN ONLY)
  server.delete('/local-security/:id', {
    preHandler: requireAuth(),
    onRequest: fastify.can(AppPermission.EQUIPMENT_EDIT),
    schema: {
      params: z.object({ id: z.string() }),
      response: {
        200: z.object({
          success: z.literal(true),
          message: z.string(),
        }),
        404: z.object({
          success: z.literal(false),
          error: z.object({
            message: z.string(),
            code: z.string(),
          }),
        }),
      },
    },
    handler: async (request: any) => {
      const { id } = request.params;
      
      const exists = await localSecurityService.findById(id);
      if (!exists) {
        throw new AppError('Local security entry not found', 404, 'NOT_FOUND');
      }
      
      await localSecurityService.softDelete(id, request.user as UserInfo);
      
      return {
        success: true as const,
        message: 'Local security entry archived',
      };
    },
  });

  // ============ OTHER EQUIPMENT ROUTES ============

  // Create other equipment entry (ADMIN ONLY)
  server.post('/other-equipment', {
    preHandler: requireAuth(),
    onRequest: fastify.canAny(AppPermission.EQUIPMENT_EDIT, AppPermission.EQUIPMENT_REQUEST_APPROVAL),
    schema: {
      body: createOtherEquipmentSchema,
      response: {
        201: otherEquipmentResponseSchema,
      },
    },
    handler: async (request: any) => {
      const result = await otherEquipmentService.create(request.body, request.user as UserInfo);
      return result;
    },
  });

  // Get all other equipment entries (ADMIN ONLY)
  server.get('/other-equipment', {
    preHandler: requireAuth(),
    onRequest: fastify.can(AppPermission.EQUIPMENT_READ),
    schema: {
      query: z.object({
        archived: z.enum(['true', 'false']).optional(),
      }),
      response: {
        200: z.array(otherEquipmentResponseSchema),
      },
    },
    handler: async (request: any) => {
      const { archived } = request.query;
      
      // TODO: Implement archived filter if needed
      return await otherEquipmentService.findAll();
    },
  });

  // Get other equipment entry by ID (ADMIN ONLY)
  server.get('/other-equipment/:id', {
    preHandler: requireAuth(),
    onRequest: fastify.can(AppPermission.EQUIPMENT_READ),
    schema: {
      params: z.object({ id: z.string() }),
      response: {
        200: otherEquipmentResponseSchema,
        404: z.object({
          success: z.literal(false),
          error: z.object({
            message: z.string(),
            code: z.string(),
          }),
        }),
      },
    },
    handler: async (request: any) => {
      const { id } = request.params;
      const entry = await otherEquipmentService.findById(id);
      
      if (!entry) {
        throw new AppError('Other equipment entry not found', 404, 'NOT_FOUND');
      }
      
      return entry;
    },
  });

  // Update other equipment entry (ADMIN ONLY)
  server.put('/other-equipment/:id', {
    preHandler: requireAuth(),
    onRequest: fastify.canAny(AppPermission.EQUIPMENT_EDIT, AppPermission.EQUIPMENT_REQUEST_APPROVAL),
    schema: {
      params: z.object({ id: z.string() }),
      body: updateOtherEquipmentSchema,
      response: {
        200: otherEquipmentResponseSchema,
        404: z.object({
          success: z.literal(false),
          error: z.object({
            message: z.string(),
            code: z.string(),
          }),
        }),
      },
    },
    handler: async (request: any) => {
      const { id } = request.params;
      const updated = await otherEquipmentService.update(id, request.body, request.user as UserInfo);
      
      if (!updated) {
        throw new AppError('Other equipment entry not found', 404, 'NOT_FOUND');
      }
      
      return updated;
    },
  });

  // Delete (archive) other equipment entry (ADMIN ONLY)
  server.delete('/other-equipment/:id', {
    preHandler: requireAuth(),
    onRequest: fastify.can(AppPermission.EQUIPMENT_EDIT),
    schema: {
      params: z.object({ id: z.string() }),
      response: {
        200: z.object({
          success: z.literal(true),
          message: z.string(),
        }),
        404: z.object({
          success: z.literal(false),
          error: z.object({
            message: z.string(),
            code: z.string(),
          }),
        }),
      },
    },
    handler: async (request: any) => {
      const { id } = request.params;
      
      const exists = await otherEquipmentService.findById(id);
      if (!exists) {
        throw new AppError('Other equipment entry not found', 404, 'NOT_FOUND');
      }
      
      await otherEquipmentService.softDelete(id, request.user as UserInfo);
      
      return {
        success: true as const,
        message: 'Other equipment entry archived',
      };
    },
  });
};

export default localITRoutes;
