import { McpServer } from '@modelcontextprotocol/sdk/server/mcp';
import { z } from 'zod';
import { isDemoUser, getCurrentUser } from '../../services/authService';
import {
  getOwnPlan, getActivePlan, getActivePlanId, getPlanData,
  updatePlan, setUserColor,
  sendInvite as sendVacayInvite, acceptInvite, declineInvite, cancelInvite, dissolvePlan,
  getAvailableUsers,
  listYears, addYear, deleteYear,
  getEntries as getVacayEntries, toggleEntry, toggleCompanyHoliday,
  getStats as getVacayStats, updateStats as updateVacayStats,
  addHolidayCalendar, updateHolidayCalendar, deleteHolidayCalendar,
  getCountries as getHolidayCountries, getHolidays,
} from '../../services/vacayService';
import { isAddonEnabled } from '../../services/adminService';
import { ADDON_IDS } from '../../addons';
import {
  TOOL_ANNOTATIONS_READONLY, TOOL_ANNOTATIONS_WRITE,
  TOOL_ANNOTATIONS_DELETE, TOOL_ANNOTATIONS_NON_IDEMPOTENT,
  demoDenied, ok,
} from './_shared';
import { canRead, canWrite } from '../scopes';

export function registerVacayTools(server: McpServer, userId: number, scopes: string[] | null): void {
  const R = canRead(scopes, 'vacay');
  const W = canWrite(scopes, 'vacay');

  if (isAddonEnabled(ADDON_IDS.VACAY)) {
    if (R) server.registerTool(
      'get_vacay_plan',
      {
        description: "Get the current user's active vacation plan (own or joined).",
        inputSchema: {},
        annotations: TOOL_ANNOTATIONS_READONLY,
      },
      async () => {
        const plan = getPlanData(userId);
        return ok({ plan });
      }
    );

    if (W) server.registerTool(
      'update_vacay_plan',
      {
        description: 'Update vacation plan settings (weekends blocking, holidays, carry-over).',
        inputSchema: {
          block_weekends: z.boolean().optional(),
          holidays_enabled: z.boolean().optional(),
          holidays_region: z.string().nullable().optional(),
          company_holidays_enabled: z.boolean().optional(),
          carry_over_enabled: z.boolean().optional(),
        },
        annotations: TOOL_ANNOTATIONS_WRITE,
      },
      async ({ block_weekends, holidays_enabled, holidays_region, company_holidays_enabled, carry_over_enabled }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        await updatePlan(planId, { block_weekends, holidays_enabled, holidays_region, company_holidays_enabled, carry_over_enabled }, undefined);
        return ok({ success: true });
      }
    );

    if (W) server.registerTool(
      'set_vacay_color',
      {
        description: "Set the current user's color in the vacation plan calendar.",
        inputSchema: {
          color: z.string().describe('Hex color e.g. #6366f1'),
        },
        annotations: TOOL_ANNOTATIONS_WRITE,
      },
      async ({ color }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        setUserColor(userId, planId, color, undefined);
        return ok({ success: true });
      }
    );

    if (R) server.registerTool(
      'get_available_vacay_users',
      {
        description: 'List users who can be invited to the current vacation plan.',
        inputSchema: {},
        annotations: TOOL_ANNOTATIONS_READONLY,
      },
      async () => {
        const planId = getActivePlanId(userId);
        const users = getAvailableUsers(userId, planId);
        return ok({ users });
      }
    );

    if (W) server.registerTool(
      'send_vacay_invite',
      {
        description: 'Invite a user to join the vacation plan by their user ID.',
        inputSchema: {
          targetUserId: z.number().int().positive(),
        },
        annotations: TOOL_ANNOTATIONS_NON_IDEMPOTENT,
      },
      async ({ targetUserId }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        const me = getCurrentUser(userId);
        if (!me) return { content: [{ type: 'text' as const, text: 'User not found.' }], isError: true };
        const result = sendVacayInvite(planId, userId, me.username, me.email, targetUserId);
        if (result.error) return { content: [{ type: 'text' as const, text: result.error }], isError: true };
        return ok({ success: true });
      }
    );

    if (W) server.registerTool(
      'accept_vacay_invite',
      {
        description: 'Accept a pending invitation to join another user\'s vacation plan.',
        inputSchema: {
          planId: z.number().int().positive(),
        },
        annotations: TOOL_ANNOTATIONS_NON_IDEMPOTENT,
      },
      async ({ planId }) => {
        if (isDemoUser(userId)) return demoDenied();
        const result = acceptInvite(userId, planId, undefined);
        if (result.error) return { content: [{ type: 'text' as const, text: result.error }], isError: true };
        return ok({ success: true });
      }
    );

    if (W) server.registerTool(
      'decline_vacay_invite',
      {
        description: 'Decline a pending vacation plan invitation.',
        inputSchema: {
          planId: z.number().int().positive(),
        },
        annotations: TOOL_ANNOTATIONS_WRITE,
      },
      async ({ planId }) => {
        declineInvite(userId, planId, undefined);
        return ok({ success: true });
      }
    );

    if (W) server.registerTool(
      'cancel_vacay_invite',
      {
        description: 'Cancel an outgoing invitation (owner cancels invite they sent).',
        inputSchema: {
          targetUserId: z.number().int().positive(),
        },
        annotations: TOOL_ANNOTATIONS_WRITE,
      },
      async ({ targetUserId }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        cancelInvite(planId, targetUserId);
        return ok({ success: true });
      }
    );

    if (W) server.registerTool(
      'dissolve_vacay_plan',
      {
        description: 'Dissolve the shared plan — all members are removed and everyone returns to their own individual plan.',
        inputSchema: {},
        annotations: TOOL_ANNOTATIONS_DELETE,
      },
      async () => {
        if (isDemoUser(userId)) return demoDenied();
        dissolvePlan(userId, undefined);
        return ok({ success: true });
      }
    );

    if (R) server.registerTool(
      'list_vacay_years',
      {
        description: 'List calendar years tracked in the current vacation plan.',
        inputSchema: {},
        annotations: TOOL_ANNOTATIONS_READONLY,
      },
      async () => {
        const planId = getActivePlanId(userId);
        const years = listYears(planId);
        return ok({ years });
      }
    );

    if (W) server.registerTool(
      'add_vacay_year',
      {
        description: 'Add a calendar year to the vacation plan.',
        inputSchema: {
          year: z.number().int().min(2000).max(2100),
        },
        annotations: TOOL_ANNOTATIONS_NON_IDEMPOTENT,
      },
      async ({ year }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        const years = addYear(planId, year, undefined);
        return ok({ years });
      }
    );

    if (W) server.registerTool(
      'delete_vacay_year',
      {
        description: 'Remove a calendar year from the vacation plan.',
        inputSchema: {
          year: z.number().int(),
        },
        annotations: TOOL_ANNOTATIONS_DELETE,
      },
      async ({ year }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        const years = deleteYear(planId, year, undefined);
        return ok({ years });
      }
    );

    if (R) server.registerTool(
      'get_vacay_entries',
      {
        description: 'Get all vacation day entries for a plan and year.',
        inputSchema: {
          year: z.number().int(),
        },
        annotations: TOOL_ANNOTATIONS_READONLY,
      },
      async ({ year }) => {
        const planId = getActivePlanId(userId);
        const entries = getVacayEntries(planId, String(year));
        return ok({ entries });
      }
    );

    if (W) server.registerTool(
      'toggle_vacay_entry',
      {
        description: 'Toggle a day on or off as a vacation day for the current user.',
        inputSchema: {
          date: z.string().describe('ISO date YYYY-MM-DD'),
        },
        annotations: TOOL_ANNOTATIONS_NON_IDEMPOTENT,
      },
      async ({ date }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        const result = toggleEntry(userId, planId, date, undefined);
        return ok(result);
      }
    );

    if (W) server.registerTool(
      'toggle_company_holiday',
      {
        description: 'Toggle a date as a company holiday for the whole plan.',
        inputSchema: {
          date: z.string(),
          note: z.string().optional(),
        },
        annotations: TOOL_ANNOTATIONS_NON_IDEMPOTENT,
      },
      async ({ date, note }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        const result = toggleCompanyHoliday(planId, date, note, undefined);
        return ok(result);
      }
    );

    if (R) server.registerTool(
      'get_vacay_stats',
      {
        description: 'Get vacation statistics for a specific year (days used, remaining, carried over).',
        inputSchema: {
          year: z.number().int(),
        },
        annotations: TOOL_ANNOTATIONS_READONLY,
      },
      async ({ year }) => {
        const planId = getActivePlanId(userId);
        const stats = getVacayStats(planId, year);
        return ok({ stats });
      }
    );

    if (W) server.registerTool(
      'update_vacay_stats',
      {
        description: 'Update the vacation day allowance for a specific user and year.',
        inputSchema: {
          year: z.number().int(),
          vacationDays: z.number().int().min(0),
        },
        annotations: TOOL_ANNOTATIONS_WRITE,
      },
      async ({ year, vacationDays }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        updateVacayStats(userId, planId, year, vacationDays, undefined);
        return ok({ success: true });
      }
    );

    if (W) server.registerTool(
      'add_holiday_calendar',
      {
        description: 'Add a public holiday calendar (by region code) to the vacation plan.',
        inputSchema: {
          region: z.string().describe('Country/region code e.g. US, GB, DE'),
          label: z.string().nullable().optional(),
          color: z.string().optional(),
          sortOrder: z.number().int().optional(),
        },
        annotations: TOOL_ANNOTATIONS_NON_IDEMPOTENT,
      },
      async ({ region, label, color, sortOrder }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        const calendar = addHolidayCalendar(planId, region, label ?? null, color, sortOrder, undefined);
        return ok({ calendar });
      }
    );

    if (W) server.registerTool(
      'update_holiday_calendar',
      {
        description: 'Update label or color for a holiday calendar.',
        inputSchema: {
          calendarId: z.number().int().positive(),
          label: z.string().nullable().optional(),
          color: z.string().optional(),
        },
        annotations: TOOL_ANNOTATIONS_WRITE,
      },
      async ({ calendarId, label, color }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        const cal = updateHolidayCalendar(calendarId, planId, { label, color }, undefined);
        if (!cal) return { content: [{ type: 'text' as const, text: 'Holiday calendar not found.' }], isError: true };
        return ok({ calendar: cal });
      }
    );

    if (W) server.registerTool(
      'delete_holiday_calendar',
      {
        description: 'Remove a holiday calendar from the vacation plan.',
        inputSchema: {
          calendarId: z.number().int().positive(),
        },
        annotations: TOOL_ANNOTATIONS_DELETE,
      },
      async ({ calendarId }) => {
        if (isDemoUser(userId)) return demoDenied();
        const planId = getActivePlanId(userId);
        deleteHolidayCalendar(calendarId, planId, undefined);
        return ok({ success: true });
      }
    );

    if (R) server.registerTool(
      'list_holiday_countries',
      {
        description: 'List countries available for public holiday calendars.',
        inputSchema: {},
        annotations: TOOL_ANNOTATIONS_READONLY,
      },
      async () => {
        const result = await getHolidayCountries();
        if (result.error) return { content: [{ type: 'text' as const, text: result.error }], isError: true };
        return ok({ countries: result.data });
      }
    );

    if (R) server.registerTool(
      'list_holidays',
      {
        description: 'List public holidays for a country and year.',
        inputSchema: {
          country: z.string().describe('ISO 3166-1 alpha-2 code'),
          year: z.number().int(),
        },
        annotations: TOOL_ANNOTATIONS_READONLY,
      },
      async ({ country, year }) => {
        const result = await getHolidays(String(year), country);
        if (result.error) return { content: [{ type: 'text' as const, text: result.error }], isError: true };
        return ok({ holidays: result.data });
      }
    );
  }
}
