/**
 * System Config Controller
 *
 * HTTP controller for system configuration endpoints
 */

import { Request, Response } from 'express';
import { SystemConfigService } from './system-config.service';
import { SystemConfigSchema, SystemConfigKeySchema } from './dtos/system-config.dto';
import { ZodError } from 'zod';

export class SystemConfigController {
  constructor(private service: SystemConfigService) {}

  async getPublic(req: Request, res: Response): Promise<void> {
    try {
      const configs = await this.service.getPublicConfigs();
      res.json({
        success: true,
        data: configs.map(config => ({
          ...config,
          value: this.service.parseValue(config.value, config.dataType),
        })),
      });
    } catch (error) {
      res.status(500).json({
        success: false,
        error: 'Failed to fetch public configs',
      });
    }
  }

  async getAll(req: Request, res: Response): Promise<void> {
    try {
      const configs = await this.service.getAllConfigs();
      res.json({
        success: true,
        data: configs,
      });
    } catch (error) {
      res.status(500).json({
        success: false,
        error: 'Failed to fetch configs',
      });
    }
  }

  async getByKey(req: Request, res: Response): Promise<void> {
    try {
      const { key } = SystemConfigKeySchema.parse(req.params);
      const config = await this.service.getParsed(key);

      if (config === null) {
        res.status(404).json({
          success: false,
          error: 'Config not found',
        });
        return;
      }

      res.json({
        success: true,
        data: { key, value: config },
      });
    } catch (error) {
      if (error instanceof ZodError) {
        res.status(400).json({
          success: false,
          error: 'Invalid key format',
          details: error.errors,
        });
        return;
      }
      res.status(500).json({
        success: false,
        error: 'Failed to fetch config',
      });
    }
  }

  async getByCategory(req: Request, res: Response): Promise<void> {
    try {
      const { category } = req.params;
      const includePrivate = req.query.includePrivate === 'true';

      const configs = await this.service.getByCategory(category, includePrivate);
      res.json({
        success: true,
        data: configs.map(config => ({
          ...config,
          value: this.service.parseValue(config.value, config.dataType),
        })),
      });
    } catch (error) {
      res.status(500).json({
        success: false,
        error: 'Failed to fetch configs by category',
      });
    }
  }

  async upsert(req: Request, res: Response): Promise<void> {
    try {
      const data = SystemConfigSchema.parse(req.body);
      const userId = (req as any).user?.id;

      await this.service.upsert(data, userId);

      res.json({
        success: true,
        message: 'Configuration saved successfully',
        data: { key: data.key },
      });
    } catch (error) {
      if (error instanceof ZodError) {
        res.status(400).json({
          success: false,
          error: 'Validation failed',
          details: error.errors,
        });
        return;
      }
      res.status(500).json({
        success: false,
        error: 'Failed to save configuration',
      });
    }
  }

  async updateValue(req: Request, res: Response): Promise<void> {
    try {
      const { key } = SystemConfigKeySchema.parse(req.params);
      const { value } = req.body;

      if (typeof value !== 'string') {
        res.status(400).json({
          success: false,
          error: 'Value must be a string',
        });
        return;
      }

      const userId = (req as any).user?.id;
      await this.service.updateValue(key, value, userId);

      res.json({
        success: true,
        message: 'Configuration updated successfully',
        data: { key },
      });
    } catch (error) {
      if (error instanceof ZodError) {
        res.status(400).json({
          success: false,
          error: 'Invalid key format',
          details: error.errors,
        });
        return;
      }
      if (error instanceof Error && error.message.includes('not found')) {
        res.status(404).json({
          success: false,
          error: error.message,
        });
        return;
      }
      res.status(500).json({
        success: false,
        error: 'Failed to update configuration',
      });
    }
  }

  async delete(req: Request, res: Response): Promise<void> {
    try {
      const { key } = SystemConfigKeySchema.parse(req.params);
      await this.service.delete(key);

      res.json({
        success: true,
        message: 'Configuration deleted successfully',
        data: { key },
      });
    } catch (error) {
      if (error instanceof ZodError) {
        res.status(400).json({
          success: false,
          error: 'Invalid key format',
          details: error.errors,
        });
        return;
      }
      res.status(500).json({
        success: false,
        error: 'Failed to delete configuration',
      });
    }
  }

  async getChangeHistory(req: Request, res: Response): Promise<void> {
    try {
      const { key } = SystemConfigKeySchema.parse(req.params);
      const history = await this.service.getChangeHistory(key);

      res.json({
        success: true,
        data: { key, history },
      });
    } catch (error) {
      if (error instanceof ZodError) {
        res.status(400).json({
          success: false,
          error: 'Invalid key format',
          details: error.errors,
        });
        return;
      }
      res.status(500).json({
        success: false,
        error: 'Failed to fetch change history',
      });
    }
  }
}
