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 { CloverClient } from './clients/clover.js';
import { CloverConfig } from './types/index.js';

// Tool imports
import { createOrdersTools } from './tools/orders-tools.js';
import { createInventoryTools } from './tools/inventory-tools.js';
import { createCustomersTools } from './tools/customers-tools.js';
import { createEmployeesTools } from './tools/employees-tools.js';
import { createPaymentsTools } from './tools/payments-tools.js';
import { createMerchantsTools } from './tools/merchants-tools.js';
import { createDiscountsTools } from './tools/discounts-tools.js';
import { createTaxesTools } from './tools/taxes-tools.js';
import { createReportsTools } from './tools/reports-tools.js';
import { createCashTools } from './tools/cash-tools.js';
import { createLineItemsTools } from './tools/line-items-tools.js';
import { createRefundsTools } from './tools/refunds-tools.js';
import { createCategoriesTools } from './tools/categories-tools.js';
import { createModifiersTools } from './tools/modifiers-tools.js';
import { createTipsTools } from './tools/tips-tools.js';
import { createShiftsTools } from './tools/shifts-tools.js';
import { createDevicesTools } from './tools/devices-tools.js';
import { createAppsTools } from './tools/apps-tools.js';

// React app imports
import { readFileSync, readdirSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

export class CloverServer {
  private server: Server;
  private client: CloverClient;
  private tools: Map<string, any>;
  private apps: Map<string, string>;

  constructor(config: CloverConfig) {
    this.server = new Server(
      {
        name: 'clover-server',
        version: '1.0.0',
      },
      {
        capabilities: {
          tools: {},
          resources: {},
        },
      }
    );

    this.client = new CloverClient(config);
    this.tools = new Map();
    this.apps = new Map();

    this.initializeTools();
    this.loadApps();
    this.setupHandlers();
  }

  private initializeTools() {
    const toolGroups = [
      createOrdersTools(this.client),
      createInventoryTools(this.client),
      createCustomersTools(this.client),
      createEmployeesTools(this.client),
      createPaymentsTools(this.client),
      createMerchantsTools(this.client),
      createDiscountsTools(this.client),
      createTaxesTools(this.client),
      createReportsTools(this.client),
      createCashTools(this.client),
      createLineItemsTools(this.client),
      createRefundsTools(this.client),
      createCategoriesTools(this.client),
      createModifiersTools(this.client),
      createTipsTools(this.client),
      createShiftsTools(this.client),
      createDevicesTools(this.client),
      createAppsTools(this.client),
    ];

    toolGroups.forEach((group) => {
      Object.entries(group).forEach(([name, tool]) => {
        this.tools.set(name, tool);
      });
    });
  }

  private loadApps() {
    const appsDir = join(__dirname, 'ui', 'react-app');
    try {
      const files = readdirSync(appsDir).filter((f) => f.endsWith('.tsx'));
      
      files.forEach((file) => {
        const appName = file.replace('.tsx', '');
        const content = readFileSync(join(appsDir, file), 'utf-8');
        this.apps.set(appName, content);
      });
    } catch (error) {
      console.warn('Could not load React apps:', error);
    }
  }

  private setupHandlers() {
    this.server.setRequestHandler(ListToolsRequestSchema, async () => {
      const tools = Array.from(this.tools.entries()).map(([name, tool]) => ({
        name,
        description: tool.description,
        inputSchema: tool.inputSchema,
      }));

      return { tools };
    });

    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { name, arguments: args } = request.params;

      const tool = this.tools.get(name);
      if (!tool) {
        throw new Error(`Unknown tool: ${name}`);
      }

      try {
        const result = await tool.handler(args || {});
        return {
          content: [
            {
              type: 'text',
              text: JSON.stringify(result, null, 2),
            },
          ],
        };
      } catch (error: any) {
        return {
          content: [
            {
              type: 'text',
              text: `Error: ${error.message}`,
            },
          ],
          isError: true,
        };
      }
    });

    this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
      const resources = Array.from(this.apps.keys()).map((appName) => ({
        uri: `clover://app/${appName}`,
        name: appName.replace(/-/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase()),
        mimeType: 'text/tsx',
        description: `Clover ${appName.replace(/-/g, ' ')} React app`,
      }));

      return { resources };
    });

    this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
      const uri = request.params.uri;
      const match = uri.match(/^clover:\/\/app\/(.+)$/);

      if (!match) {
        throw new Error(`Invalid resource URI: ${uri}`);
      }

      const appName = match[1];
      const appCode = this.apps.get(appName);

      if (!appCode) {
        throw new Error(`App not found: ${appName}`);
      }

      return {
        contents: [
          {
            uri,
            mimeType: 'text/tsx',
            text: appCode,
          },
        ],
      };
    });
  }

  async run() {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
  }
}
