// src/controllers/admin.controller.js
// 관리자 컨트롤러

const { LLMProvider, User, UsageLog, ApiKey } = require('../models');
const { Op } = require('sequelize');
const logger = require('../config/logger.config');

// ===== LLM 프로바이더 관리 =====

/**
 * LLM 프로바이더 목록 조회
 */
exports.getProviders = async (req, res, next) => {
  try {
    const providers = await LLMProvider.findAll({
      order: [['priority', 'ASC']],
      attributes: [
        'id',
        'name',
        'displayName',
        'endpoint',
        'modelName',
        'priority',
        'maxTokens',
        'temperature',
        'timeoutMs',
        'costPer1kInputTokens',
        'costPer1kOutputTokens',
        'isActive',
        'isHealthy',
        'lastHealthCheck',
        'createdAt',
        'updatedAt',
        // API 키는 마스킹해서 반환
        'apiKey',
      ],
    });

    // API 키 마스킹
    const maskedProviders = providers.map((p) => {
      const data = p.toJSON();
      if (data.apiKey) {
        // 앞 8자만 보여주고 나머지는 마스킹
        data.apiKey = data.apiKey.substring(0, 8) + '****' + data.apiKey.slice(-4);
        data.hasApiKey = true;
      } else {
        data.hasApiKey = false;
      }
      return data;
    });

    return res.json({
      success: true,
      data: maskedProviders,
    });
  } catch (error) {
    return next(error);
  }
};

/**
 * LLM 프로바이더 추가
 */
exports.createProvider = async (req, res, next) => {
  try {
    const {
      name,
      displayName,
      endpoint,
      apiKey,
      modelName,
      priority = 50,
      maxTokens = 4096,
      temperature = 0.7,
      timeoutMs = 60000,
      costPer1kInputTokens = 0,
      costPer1kOutputTokens = 0,
    } = req.body;

    // 중복 이름 확인
    const existing = await LLMProvider.findOne({ where: { name } });
    if (existing) {
      return res.status(409).json({
        success: false,
        error: {
          code: 'PROVIDER_EXISTS',
          message: '이미 존재하는 프로바이더 이름입니다.',
        },
      });
    }

    const provider = await LLMProvider.create({
      name,
      displayName,
      endpoint,
      apiKey,
      modelName,
      priority,
      maxTokens,
      temperature,
      timeoutMs,
      costPer1kInputTokens,
      costPer1kOutputTokens,
      isActive: true,
      isHealthy: true,
    });

    logger.info(`LLM 프로바이더 추가: ${name} (${modelName})`);

    return res.status(201).json({
      success: true,
      data: {
        id: provider.id,
        name: provider.name,
        displayName: provider.displayName,
        modelName: provider.modelName,
        priority: provider.priority,
        isActive: provider.isActive,
        message: 'LLM 프로바이더가 추가되었습니다.',
      },
    });
  } catch (error) {
    return next(error);
  }
};

/**
 * LLM 프로바이더 수정
 */
exports.updateProvider = async (req, res, next) => {
  try {
    const { id } = req.params;
    const updates = req.body;

    const provider = await LLMProvider.findByPk(id);
    if (!provider) {
      return res.status(404).json({
        success: false,
        error: {
          code: 'PROVIDER_NOT_FOUND',
          message: 'LLM 프로바이더를 찾을 수 없습니다.',
        },
      });
    }

    // 허용된 필드만 업데이트
    const allowedFields = [
      'displayName',
      'endpoint',
      'apiKey',
      'modelName',
      'priority',
      'maxTokens',
      'temperature',
      'timeoutMs',
      'costPer1kInputTokens',
      'costPer1kOutputTokens',
      'isActive',
      'isHealthy',
    ];

    allowedFields.forEach((field) => {
      if (updates[field] !== undefined) {
        provider[field] = updates[field];
      }
    });

    await provider.save();

    logger.info(`LLM 프로바이더 수정: ${provider.name}`);

    return res.json({
      success: true,
      data: {
        id: provider.id,
        name: provider.name,
        displayName: provider.displayName,
        modelName: provider.modelName,
        isActive: provider.isActive,
        message: 'LLM 프로바이더가 수정되었습니다.',
      },
    });
  } catch (error) {
    return next(error);
  }
};

/**
 * LLM 프로바이더 삭제
 */
exports.deleteProvider = async (req, res, next) => {
  try {
    const { id } = req.params;

    const provider = await LLMProvider.findByPk(id);
    if (!provider) {
      return res.status(404).json({
        success: false,
        error: {
          code: 'PROVIDER_NOT_FOUND',
          message: 'LLM 프로바이더를 찾을 수 없습니다.',
        },
      });
    }

    const providerName = provider.name;
    await provider.destroy();

    logger.info(`LLM 프로바이더 삭제: ${providerName}`);

    return res.json({
      success: true,
      data: {
        message: 'LLM 프로바이더가 삭제되었습니다.',
      },
    });
  } catch (error) {
    return next(error);
  }
};

// ===== 사용자 관리 =====

/**
 * 사용자 목록 조회
 */
exports.getUsers = async (req, res, next) => {
  try {
    const page = parseInt(req.query.page, 10) || 1;
    const limit = parseInt(req.query.limit, 10) || 100;
    const offset = (page - 1) * limit;

    const { count, rows: users } = await User.findAndCountAll({
      attributes: [
        'id',
        'email',
        'name',
        'role',
        'status',
        'plan',
        'monthlyTokenLimit',
        'lastLoginAt',
        'createdAt',
      ],
      order: [['createdAt', 'DESC']],
      limit,
      offset,
    });

    // 페이지네이션 없이 간단한 배열로 반환 (프론트엔드 호환)
    return res.json({
      success: true,
      data: users,
    });
  } catch (error) {
    return next(error);
  }
};

/**
 * 사용자 정보 수정
 */
exports.updateUser = async (req, res, next) => {
  try {
    const { id } = req.params;
    const { role, status, plan, monthlyTokenLimit } = req.body;

    const user = await User.findByPk(id);
    if (!user) {
      return res.status(404).json({
        success: false,
        error: {
          code: 'USER_NOT_FOUND',
          message: '사용자를 찾을 수 없습니다.',
        },
      });
    }

    if (role) user.role = role;
    if (status) user.status = status;
    if (plan) user.plan = plan;
    if (monthlyTokenLimit !== undefined) user.monthlyTokenLimit = monthlyTokenLimit;

    await user.save();

    logger.info(`사용자 정보 수정: ${user.email} (role: ${user.role}, status: ${user.status})`);

    return res.json({
      success: true,
      data: user.toSafeJSON(),
    });
  } catch (error) {
    return next(error);
  }
};

// ===== 시스템 통계 =====

/**
 * 사용자별 사용량 통계
 */
exports.getUsageByUser = async (req, res, next) => {
  try {
    const days = parseInt(req.query.days, 10) || 7;
    const startDate = new Date();
    startDate.setDate(startDate.getDate() - days);
    startDate.setHours(0, 0, 0, 0);

    // 사용자별 집계 (raw SQL 사용)
    const userStats = await UsageLog.sequelize.query(`
      SELECT 
        u.id as "userId",
        u.email,
        u.name,
        COALESCE(SUM(ul.total_tokens), 0) as "totalTokens",
        COALESCE(SUM(ul.cost_usd), 0) as "totalCost",
        COUNT(ul.id) as "requestCount"
      FROM users u
      LEFT JOIN usage_logs ul ON u.id = ul.user_id AND ul.created_at >= :startDate
      GROUP BY u.id, u.email, u.name
      HAVING COUNT(ul.id) > 0
      ORDER BY SUM(ul.total_tokens) DESC NULLS LAST
    `, {
      replacements: { startDate },
      type: UsageLog.sequelize.QueryTypes.SELECT,
    });

    // 데이터 정리
    const result = userStats.map((stat) => ({
      userId: stat.userId,
      email: stat.email || 'Unknown',
      name: stat.name || '',
      totalTokens: parseInt(stat.totalTokens, 10) || 0,
      totalCost: parseFloat(stat.totalCost) || 0,
      requestCount: parseInt(stat.requestCount, 10) || 0,
    }));

    return res.json({
      success: true,
      data: result,
    });
  } catch (error) {
    return next(error);
  }
};

/**
 * 프로바이더별 사용량 통계
 */
exports.getUsageByProvider = async (req, res, next) => {
  try {
    const days = parseInt(req.query.days, 10) || 7;
    const startDate = new Date();
    startDate.setDate(startDate.getDate() - days);
    startDate.setHours(0, 0, 0, 0);

    // 프로바이더별 집계 (컬럼명 수정: providerName, modelName)
    const providerStats = await UsageLog.findAll({
      where: {
        createdAt: { [Op.gte]: startDate },
      },
      attributes: [
        'providerName',
        'modelName',
        [UsageLog.sequelize.fn('SUM', UsageLog.sequelize.col('total_tokens')), 'totalTokens'],
        [UsageLog.sequelize.fn('SUM', UsageLog.sequelize.col('prompt_tokens')), 'promptTokens'],
        [UsageLog.sequelize.fn('SUM', UsageLog.sequelize.col('completion_tokens')), 'completionTokens'],
        [UsageLog.sequelize.fn('SUM', UsageLog.sequelize.col('cost_usd')), 'totalCost'],
        [UsageLog.sequelize.fn('COUNT', UsageLog.sequelize.col('id')), 'requestCount'],
        [UsageLog.sequelize.fn('AVG', UsageLog.sequelize.col('response_time_ms')), 'avgResponseTime'],
      ],
      group: ['providerName', 'modelName'],
      order: [[UsageLog.sequelize.literal('"totalTokens"'), 'DESC']],
      raw: true,
    });

    // 데이터 정리
    const result = providerStats.map((stat) => ({
      provider: stat.providerName || 'Unknown',
      model: stat.modelName || 'Unknown',
      totalTokens: parseInt(stat.totalTokens, 10) || 0,
      promptTokens: parseInt(stat.promptTokens, 10) || 0,
      completionTokens: parseInt(stat.completionTokens, 10) || 0,
      totalCost: parseFloat(stat.totalCost) || 0,
      requestCount: parseInt(stat.requestCount, 10) || 0,
      avgResponseTime: Math.round(parseFloat(stat.avgResponseTime) || 0),
    }));

    return res.json({
      success: true,
      data: result,
    });
  } catch (error) {
    return next(error);
  }
};

/**
 * 시스템 통계 조회
 */
exports.getStats = async (req, res, next) => {
  try {
    // 전체 사용자 수
    const totalUsers = await User.count();
    const activeUsers = await User.count({ where: { status: 'active' } });

    // 전체 API 키 수
    const totalApiKeys = await ApiKey.count();
    const activeApiKeys = await ApiKey.count({ where: { status: 'active' } });

    // 오늘 사용량
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const todayUsage = await UsageLog.findOne({
      where: {
        createdAt: { [Op.gte]: today },
      },
      attributes: [
        [UsageLog.sequelize.fn('SUM', UsageLog.sequelize.col('total_tokens')), 'totalTokens'],
        [UsageLog.sequelize.fn('SUM', UsageLog.sequelize.col('cost_usd')), 'totalCost'],
        [UsageLog.sequelize.fn('COUNT', UsageLog.sequelize.col('id')), 'requestCount'],
      ],
      raw: true,
    });

    // 이번 달 사용량
    const monthStart = new Date(today.getFullYear(), today.getMonth(), 1);
    const monthlyUsage = await UsageLog.findOne({
      where: {
        createdAt: { [Op.gte]: monthStart },
      },
      attributes: [
        [UsageLog.sequelize.fn('SUM', UsageLog.sequelize.col('total_tokens')), 'totalTokens'],
        [UsageLog.sequelize.fn('SUM', UsageLog.sequelize.col('cost_usd')), 'totalCost'],
        [UsageLog.sequelize.fn('COUNT', UsageLog.sequelize.col('id')), 'requestCount'],
      ],
      raw: true,
    });

    // 활성 프로바이더 수
    const activeProviders = await LLMProvider.count({ where: { isActive: true, isHealthy: true } });

    return res.json({
      success: true,
      data: {
        users: {
          total: totalUsers,
          active: activeUsers,
        },
        apiKeys: {
          total: totalApiKeys,
          active: activeApiKeys,
        },
        providers: {
          active: activeProviders,
        },
        usage: {
          today: {
            tokens: parseInt(todayUsage?.totalTokens, 10) || 0,
            cost: parseFloat(todayUsage?.totalCost) || 0,
            requests: parseInt(todayUsage?.requestCount, 10) || 0,
          },
          monthly: {
            tokens: parseInt(monthlyUsage?.totalTokens, 10) || 0,
            cost: parseFloat(monthlyUsage?.totalCost) || 0,
            requests: parseInt(monthlyUsage?.requestCount, 10) || 0,
          },
        },
      },
    });
  } catch (error) {
    return next(error);
  }
};
