import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { GustoClient } from './clients/gusto.js';
import { createEmployeeTools, employeeToolDefinitions } from './tools/employees-tools.js';
import { createCompanyTools, companyToolDefinitions } from './tools/companies-tools.js';
import { createPayrollTools, payrollToolDefinitions } from './tools/payrolls-tools.js';
import { createBenefitTools, benefitToolDefinitions } from './tools/benefits-tools.js';
import {
  createCompensationTools,
  compensationToolDefinitions,
} from './tools/compensations-tools.js';
import { createTimeOffTools, timeOffToolDefinitions } from './tools/time-off-tools.js';
import { createTaxTools, taxToolDefinitions } from './tools/tax-tools.js';
import { createContractorTools, contractorToolDefinitions } from './tools/contractors-tools.js';
import { createGarnishmentTools, garnishmentToolDefinitions } from './tools/garnishments-tools.js';
import {
  createBankAccountTools,
  bankAccountToolDefinitions,
} from './tools/bank-accounts-tools.js';

// Import React apps
import { EMPLOYEE_DASHBOARD_APP } from './ui/react-app/employee-dashboard.js';
import { EMPLOYEE_DETAIL_APP } from './ui/react-app/employee-detail.js';
import { EMPLOYEE_DIRECTORY_APP } from './ui/react-app/employee-directory.js';
import { PAYROLL_DASHBOARD_APP } from './ui/react-app/payroll-dashboard.js';
import { PAYROLL_DETAIL_APP } from './ui/react-app/payroll-detail.js';
import { PAYROLL_CALENDAR_APP } from './ui/react-app/payroll-calendar.js';
import { BENEFITS_OVERVIEW_APP } from './ui/react-app/benefits-overview.js';
import { BENEFITS_ENROLLMENT_APP } from './ui/react-app/benefits-enrollment.js';
import { COMPENSATION_GRID_APP } from './ui/react-app/compensation-grid.js';
import { TIME_OFF_TRACKER_APP } from './ui/react-app/time-off-tracker.js';
import { TIME_OFF_BALANCES_APP } from './ui/react-app/time-off-balances.js';
import { TAX_OVERVIEW_APP } from './ui/react-app/tax-overview.js';
import { CONTRACTOR_DASHBOARD_APP } from './ui/react-app/contractor-dashboard.js';
import { CONTRACTOR_PAYMENTS_APP } from './ui/react-app/contractor-payments.js';
import { GARNISHMENT_MANAGER_APP } from './ui/react-app/garnishment-manager.js';
import { BANK_ACCOUNTS_APP } from './ui/react-app/bank-accounts.js';
import { ONBOARDING_TRACKER_APP } from './ui/react-app/onboarding-tracker.js';
import { DEPARTMENT_OVERVIEW_APP } from './ui/react-app/department-overview.js';
import { PAY_HISTORY_APP } from './ui/react-app/pay-history.js';

const GUSTO_API_TOKEN = process.env.GUSTO_API_TOKEN;
if (!GUSTO_API_TOKEN) {
  throw new Error('GUSTO_API_TOKEN environment variable is required');
}

const client = new GustoClient({ apiToken: GUSTO_API_TOKEN });

// Collect all tools
const employeeTools = createEmployeeTools(client);
const companyTools = createCompanyTools(client);
const payrollTools = createPayrollTools(client);
const benefitTools = createBenefitTools(client);
const compensationTools = createCompensationTools(client);
const timeOffTools = createTimeOffTools(client);
const taxTools = createTaxTools(client);
const contractorTools = createContractorTools(client);
const garnishmentTools = createGarnishmentTools(client);
const bankAccountTools = createBankAccountTools(client);

const allTools = {
  ...employeeTools,
  ...companyTools,
  ...payrollTools,
  ...benefitTools,
  ...compensationTools,
  ...timeOffTools,
  ...taxTools,
  ...contractorTools,
  ...garnishmentTools,
  ...bankAccountTools,
};

const allToolDefinitions = [
  ...employeeToolDefinitions,
  ...companyToolDefinitions,
  ...payrollToolDefinitions,
  ...benefitToolDefinitions,
  ...compensationToolDefinitions,
  ...timeOffToolDefinitions,
  ...taxToolDefinitions,
  ...contractorToolDefinitions,
  ...garnishmentToolDefinitions,
  ...bankAccountToolDefinitions,
];

// Collect all React apps
const allApps = [
  EMPLOYEE_DASHBOARD_APP,
  EMPLOYEE_DETAIL_APP,
  EMPLOYEE_DIRECTORY_APP,
  PAYROLL_DASHBOARD_APP,
  PAYROLL_DETAIL_APP,
  PAYROLL_CALENDAR_APP,
  BENEFITS_OVERVIEW_APP,
  BENEFITS_ENROLLMENT_APP,
  COMPENSATION_GRID_APP,
  TIME_OFF_TRACKER_APP,
  TIME_OFF_BALANCES_APP,
  TAX_OVERVIEW_APP,
  CONTRACTOR_DASHBOARD_APP,
  CONTRACTOR_PAYMENTS_APP,
  GARNISHMENT_MANAGER_APP,
  BANK_ACCOUNTS_APP,
  ONBOARDING_TRACKER_APP,
  DEPARTMENT_OVERVIEW_APP,
  PAY_HISTORY_APP,
];

const server = new Server(
  {
    name: 'gusto-mcp-server',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {},
      resources: {},
    },
  }
);

// List tools handler
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: allToolDefinitions,
}));

// Call tool handler
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const toolName = request.params.name;
  const toolHandler = allTools[toolName as keyof typeof allTools];

  if (!toolHandler) {
    throw new Error(`Unknown tool: ${toolName}`);
  }

  try {
    return await toolHandler(request.params.arguments as any);
  } catch (error: any) {
    return {
      content: [
        {
          type: 'text',
          text: `Error: ${error.message || String(error)}`,
        },
      ],
      isError: true,
    };
  }
});

// List resources (React apps)
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
  resources: allApps.map((app) => ({
    uri: `gusto://app/${app.id}`,
    name: app.name,
    description: app.description,
    mimeType: 'text/html',
  })),
}));

// Read resource handler (return React app HTML)
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
  const uri = request.params.uri;
  const appId = uri.replace('gusto://app/', '');
  const app = allApps.find((a) => a.id === appId);

  if (!app) {
    throw new Error(`Unknown app: ${appId}`);
  }

  return {
    contents: [
      {
        uri,
        mimeType: 'text/html',
        text: app.html,
      },
    ],
  };
});

export async function runServer() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('Gusto MCP Server running on stdio');
}
