// src/server/features/operations/operations.routes.ts
// HTTP handlers for operations routes (check-in, linen)

import { ZodTypeProvider } from 'fastify-type-provider-zod';
import { z } from 'zod';
import type { FastifyInstance } from 'fastify';
import {
  getDailyCheckinsByDate,
  getDailyCheckinById,
  createDailyCheckin,
  patchCheckin,
  getLinenTypes,
  getInvLinenById,
  createLinenDispatchLog,
  getLinenDispatchLogByDate,
  dispatchLaundry,
  getLinenUsageReport,
  getDailyLinenUsageByDate,
  upsertDailyLinenUsage,
  syncDailyCheckins,
} from './operations.service';
import {
  createDailyCheckinSchema,
  patchDailyCheckinSchema,
  dailyCheckinResponseSchema,
  invLinenResponseSchema,
  createLinenDispatchLogSchema,
  linenDispatchLogResponseSchema,
  dispatchLaundrySchema,
  linenUsageReportSchema,
  getLinenUsageReportSchema,
  dailyLinenUsageResponseSchema,
  patchDailyLinenUsageSchema,
  syncCheckinsSchema,
  syncCheckinsResponseSchema,
} from './operations.schema';

export const operationsRoutes = async (fastify: FastifyInstance) => {
  const server = fastify.withTypeProvider<ZodTypeProvider>();

  // ==================== LINEN TYPES ====================

  // GET /api/operations/linen-types - Returns linen types reference
  server.get('/linen-types', {
    schema: {
      response: {
        200: z.object({
          success: z.boolean(),
          data: z.array(invLinenResponseSchema),
        }),
      },
    },
  }, async () => {
    const items = await getLinenTypes();
    return { success: true, data: items };
  });

  // ==================== DAILY CHECK-INS ====================

  // GET /api/operations/checkins?date=YYYY-MM-DD - Get daily check-ins by date
  server.get('/checkins', {
    schema: {
      querystring: z.object({
        date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), // YYYY-MM-DD format
      }),
      response: {
        200: z.object({
          success: z.boolean(),
          data: z.array(dailyCheckinResponseSchema),
        }),
      },
    },
  }, async (request) => {
    const { date } = request.query as { date: string };
    const checkins = await getDailyCheckinsByDate(date);
    return { success: true, data: checkins };
  });

  // GET /api/operations/checkins/:id - Get daily check-in by ID
  server.get('/checkins/:id', {
    schema: {
      params: z.object({
        id: z.string().uuid(),
      }),
      response: {
        200: z.object({
          success: z.boolean(),
          data: dailyCheckinResponseSchema,
        }),
      },
    },
  }, async (request) => {
    const { id } = request.params as { id: string };
    const checkin = await getDailyCheckinById(id);
    if (!checkin) {
      throw new Error('Check-in not found');
    }
    return { success: true, data: checkin };
  });

  // POST /api/operations/checkins - Create daily check-in
  server.post('/checkins', {
    schema: {
      body: createDailyCheckinSchema,
      response: {
        200: z.object({
          success: z.boolean(),
          data: z.object({ id: z.string() }),
        }),
      },
    },
  }, async (request) => {
    const data = request.body as any;
    const id = await createDailyCheckin(data);
    return { success: true, data: { id } };
  });

  // PATCH /api/operations/checkins/:id - Update daily check-in (auto-save)
  server.patch('/checkins/:id', {
    schema: {
      params: z.object({
        id: z.string().uuid(),
      }),
      body: patchDailyCheckinSchema,
      response: {
        200: z.object({
          success: z.boolean(),
          data: dailyCheckinResponseSchema,
        }),
      },
    },
  }, async (request) => {
    const { id } = request.params as { id: string };
    const data = request.body as any;
    const checkin = await patchCheckin(id, data);
    if (!checkin) {
      throw new Error('Check-in not found');
    }
    return { success: true, data: checkin };
  });

  // POST /api/operations/checkins/sync - Sync daily check-ins with active rooms
  server.post('/checkins/sync', {
    schema: {
      body: syncCheckinsSchema,
      response: {
        200: z.object({
          success: z.boolean(),
          data: syncCheckinsResponseSchema,
        }),
      },
    },
  }, async (request) => {
    const { date } = request.body as { date: string };
    const result = await syncDailyCheckins(date);
    return { success: true, data: result };
  });

  // ==================== LINEN DISPATCH ====================

  // GET /api/operations/laundry/dispatch-log?date=YYYY-MM-DD - Get linen dispatch log by date
  server.get('/laundry/dispatch-log', {
    schema: {
      querystring: z.object({
        date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
      }),
      response: {
        200: z.object({
          success: z.boolean(),
          data: linenDispatchLogResponseSchema.nullable(),
        }),
      },
    },
  }, async (request) => {
    const { date } = request.query as { date: string };
    const log = await getLinenDispatchLogByDate(date);
    return { success: true, data: log };
  });

  // POST /api/operations/laundry/dispatch - Dispatch linen to laundry (one-time per day)
  server.post('/laundry/dispatch', {
    schema: {
      body: dispatchLaundrySchema,
      response: {
        200: z.object({
          success: z.boolean(),
          data: z.object({
            dispatchId: z.string().nullable(),
            message: z.string(),
          }),
        }),
      },
    },
  }, async (request) => {
    const { date } = request.body as { date: string };
    const dispatchId = await dispatchLaundry(date);

    if (!dispatchId) {
      return {
        success: false,
        data: {
          dispatchId: null,
          message: 'Linen already dispatched today or no linen to dispatch',
        },
      };
    }

    return {
      success: true,
      data: {
        dispatchId,
        message: 'Linen dispatched successfully',
      },
    };
  });

  // ==================== REPORTS ====================

  // GET /api/operations/reports/linen?from=YYYY-MM-DD&to=YYYY-MM-DD - Get linen usage report
  server.get('/reports/linen', {
    schema: {
      querystring: getLinenUsageReportSchema,
      response: {
        200: z.object({
          success: z.boolean(),
          data: linenUsageReportSchema,
        }),
      },
    },
  }, async (request) => {
    const { from, to } = request.query as { from: string; to: string };
    const report = await getLinenUsageReport({ from, to });
    return { success: true, data: report };
  });

  // ==================== GLOBAL DAILY LINEN USAGE ====================

  // GET /api/operations/linen-usage?date=YYYY-MM-DD - Get daily linen usage by date
  server.get('/linen-usage', {
    schema: {
      querystring: z.object({
        date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), // YYYY-MM-DD format
      }),
      response: {
        200: z.object({
          success: z.boolean(),
          data: dailyLinenUsageResponseSchema,
        }),
      },
    },
  }, async (request) => {
    const { date } = request.query as { date: string };
    const usage = await getDailyLinenUsageByDate(date);
    return { success: true, data: usage };
  });

  // PATCH /api/operations/linen-usage - Upsert daily linen usage (update if exists, insert if not)
  server.patch('/linen-usage', {
    schema: {
      body: patchDailyLinenUsageSchema,
      response: {
        200: z.object({
          success: z.boolean(),
          data: dailyLinenUsageResponseSchema,
        }),
      },
    },
  }, async (request) => {
    const data = request.body as any;
    const user = request.user as any;
    const userRole = user?.role || 'GUEST';
    const usage = await upsertDailyLinenUsage(data, userRole);
    return { success: true, data: usage };
  });
};
