// 스마트공장 활용 로그 조회 컨트롤러
// 최고관리자(*) 전용 — 회사별 필터링 가능

import { Response } from "express";
import { AuthenticatedRequest } from "../middleware/permissionMiddleware";
import { query, queryOne } from "../database/db";
import { logger } from "../utils/logger";
import { encryptionService } from "../services/encryptionService";
import {
  sendSmartFactoryLog,
  getTodayPlanStatus,
  planDailySends,
} from "../utils/smartFactoryLog";

/**
 * GET /api/admin/smart-factory-log
 * 스마트공장 로그 목록 조회
 */
export const getSmartFactoryLogs = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const {
      companyCode,
      userId,
      sendStatus,
      dateFrom,
      dateTo,
      search,
      page = "1",
      limit = "50",
    } = req.query;

    const whereConditions: string[] = [];
    const queryParams: any[] = [];
    let paramIndex = 1;

    // 회사 필터
    if (companyCode && companyCode !== "all") {
      whereConditions.push(`sfl.company_code = $${paramIndex}`);
      queryParams.push(companyCode);
      paramIndex++;
    }

    // 사용자 필터
    if (userId && (userId as string).trim()) {
      whereConditions.push(`sfl.user_id ILIKE $${paramIndex}`);
      queryParams.push(`%${(userId as string).trim()}%`);
      paramIndex++;
    }

    // 전송 상태 필터
    if (sendStatus && sendStatus !== "all") {
      whereConditions.push(`sfl.send_status = $${paramIndex}`);
      queryParams.push(sendStatus);
      paramIndex++;
    }

    // 날짜 범위 필터
    if (dateFrom) {
      whereConditions.push(`sfl.created_at >= $${paramIndex}`);
      queryParams.push(dateFrom);
      paramIndex++;
    }
    if (dateTo) {
      whereConditions.push(`sfl.created_at < ($${paramIndex}::date + 1)`);
      queryParams.push(dateTo);
      paramIndex++;
    }

    // 통합 검색
    if (search && (search as string).trim()) {
      whereConditions.push(
        `(sfl.user_id ILIKE $${paramIndex} OR sfl.user_name ILIKE $${paramIndex} OR sfl.connect_ip ILIKE $${paramIndex} OR sfl.error_message ILIKE $${paramIndex})`
      );
      queryParams.push(`%${(search as string).trim()}%`);
      paramIndex++;
    }

    const whereClause =
      whereConditions.length > 0 ? `WHERE ${whereConditions.join(" AND ")}` : "";

    // 총 개수
    const countResult = await queryOne<{ total: string }>(
      `SELECT COUNT(*) as total FROM smart_factory_log sfl ${whereClause}`,
      queryParams
    );
    const total = parseInt(countResult?.total || "0", 10);

    // 페이지네이션
    const pageNum = Math.max(1, parseInt(page as string, 10));
    const limitNum = Math.min(100, Math.max(1, parseInt(limit as string, 10)));
    const offset = (pageNum - 1) * limitNum;

    // 데이터 조회 (회사명 JOIN)
    const logs = await query<any>(
      `SELECT sfl.*, cm.company_name
       FROM smart_factory_log sfl
       LEFT JOIN company_mng cm ON cm.company_code = sfl.company_code
       ${whereClause}
       ORDER BY sfl.created_at DESC
       LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`,
      [...queryParams, limitNum, offset]
    );

    res.status(200).json({
      success: true,
      data: logs,
      total,
      page: pageNum,
      limit: limitNum,
    });
  } catch (error) {
    logger.error("스마트공장 로그 조회 실패:", error);
    res.status(500).json({
      success: false,
      message: "스마트공장 로그 조회 중 오류가 발생했습니다.",
      error: {
        code: "SERVER_ERROR",
        details: error instanceof Error ? error.message : "알 수 없는 오류",
      },
    });
  }
};

/**
 * GET /api/admin/smart-factory-log/stats
 * 스마트공장 로그 통계 (회사별 요약)
 */
export const getSmartFactoryLogStats = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { companyCode, days = "30" } = req.query;
    const daysNum = parseInt(days as string, 10) || 30;

    const whereConditions: string[] = [
      `sfl.created_at >= NOW() - INTERVAL '${daysNum} days'`,
    ];
    const queryParams: any[] = [];
    let paramIndex = 1;

    if (companyCode && companyCode !== "all") {
      whereConditions.push(`sfl.company_code = $${paramIndex}`);
      queryParams.push(companyCode);
      paramIndex++;
    }

    const whereClause = `WHERE ${whereConditions.join(" AND ")}`;

    // 상태별 건수
    const statusCounts = await query<{ send_status: string; count: string }>(
      `SELECT send_status, COUNT(*) as count
       FROM smart_factory_log sfl
       ${whereClause}
       GROUP BY send_status`,
      queryParams
    );

    // 회사별 건수
    const companyCounts = await query<{
      company_code: string;
      company_name: string;
      count: string;
    }>(
      `SELECT sfl.company_code, COALESCE(cm.company_name, sfl.company_code) as company_name, COUNT(*) as count
       FROM smart_factory_log sfl
       LEFT JOIN company_mng cm ON cm.company_code = sfl.company_code
       ${whereClause}
       GROUP BY sfl.company_code, cm.company_name
       ORDER BY count DESC`,
      queryParams
    );

    // 일별 추이
    const dailyCounts = await query<{ date: string; count: string }>(
      `SELECT DATE(sfl.created_at) as date, COUNT(*) as count
       FROM smart_factory_log sfl
       ${whereClause}
       GROUP BY DATE(sfl.created_at)
       ORDER BY date DESC
       LIMIT ${daysNum}`,
      queryParams
    );

    // 전체 건수
    const totalResult = await queryOne<{ total: string }>(
      `SELECT COUNT(*) as total FROM smart_factory_log sfl ${whereClause}`,
      queryParams
    );

    res.status(200).json({
      success: true,
      data: {
        total: parseInt(totalResult?.total || "0", 10),
        statusCounts: statusCounts.map((r) => ({
          status: r.send_status,
          count: parseInt(r.count, 10),
        })),
        companyCounts: companyCounts.map((r) => ({
          companyCode: r.company_code,
          companyName: r.company_name,
          count: parseInt(r.count, 10),
        })),
        dailyCounts: dailyCounts.map((r) => ({
          date: r.date,
          count: parseInt(r.count, 10),
        })),
      },
    });
  } catch (error) {
    logger.error("스마트공장 로그 통계 조회 실패:", error);
    res.status(500).json({
      success: false,
      message: "통계 조회 중 오류가 발생했습니다.",
      error: {
        code: "SERVER_ERROR",
        details: error instanceof Error ? error.message : "알 수 없는 오류",
      },
    });
  }
};

// ─── 스케줄 관리 API ───

/**
 * GET /api/admin/smart-factory-log/schedules
 */
export const getSchedules = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const schedules = await query<any>(
      `SELECT s.*, cm.company_name
       FROM smart_factory_schedule s
       LEFT JOIN company_mng cm ON cm.company_code = s.company_code
       ORDER BY s.company_code`
    );
    res.json({ success: true, data: schedules });
  } catch (error) {
    logger.error("스케줄 조회 실패:", error);
    res.status(500).json({ success: false, message: "스케줄 조회 실패" });
  }
};

/**
 * POST /api/admin/smart-factory-log/schedules
 */
export const upsertSchedule = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { companyCode, isActive, timeStart, timeEnd, excludeWeekend, excludeHolidays, dailyCount } = req.body;

    if (!companyCode) {
      res.status(400).json({ success: false, message: "회사코드는 필수입니다." });
      return;
    }

    await query(
      `INSERT INTO smart_factory_schedule (company_code, is_active, time_start, time_end, exclude_weekend, exclude_holidays, daily_count, updated_at)
       VALUES ($1, $2, $3, $4, $5, $6, $7, NOW())
       ON CONFLICT (company_code) DO UPDATE SET
         is_active = $2, time_start = $3, time_end = $4,
         exclude_weekend = $5, exclude_holidays = $6, daily_count = $7, updated_at = NOW()`,
      [
        companyCode,
        isActive ?? false,
        timeStart || "08:30",
        timeEnd || "17:30",
        excludeWeekend ?? true,
        excludeHolidays ?? true,
        Math.max(1, Math.min(3, dailyCount || 1)),
      ]
    );

    // 스케줄 변경 후 오늘 계획 즉시 재생성 (이미 전송된 사용자는 자동 제외됨)
    await planDailySends();
    res.json({ success: true, message: "스케줄이 저장되었습니다." });
  } catch (error) {
    logger.error("스케줄 저장 실패:", error);
    res.status(500).json({ success: false, message: "스케줄 저장 실패" });
  }
};

/**
 * DELETE /api/admin/smart-factory-log/schedules/:companyCode
 */
export const deleteSchedule = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { companyCode } = req.params;
    await query("DELETE FROM smart_factory_schedule WHERE company_code = $1", [companyCode]);
    res.json({ success: true, message: "스케줄이 삭제되었습니다." });
  } catch (error) {
    logger.error("스케줄 삭제 실패:", error);
    res.status(500).json({ success: false, message: "스케줄 삭제 실패" });
  }
};

/**
 * POST /api/admin/smart-factory-log/schedules/:companyCode/run-now
 */
/**
 * GET /api/admin/smart-factory-log/schedules/today-plan
 */
export const getTodayPlanHandler = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const plan = getTodayPlanStatus();
    res.json({ success: true, data: plan });
  } catch (error) {
    logger.error("오늘 계획 조회 실패:", error);
    res.status(500).json({ success: false, message: "오늘 계획 조회 실패" });
  }
};

// ─── 공휴일 관리 API ───

/**
 * GET /api/admin/smart-factory-log/holidays
 */
export const getHolidays = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const holidays = await query<any>(
      "SELECT id, holiday_date, holiday_name, created_at FROM smart_factory_holidays ORDER BY holiday_date"
    );
    res.json({ success: true, data: holidays });
  } catch (error) {
    logger.error("공휴일 조회 실패:", error);
    res.status(500).json({ success: false, message: "공휴일 조회 실패" });
  }
};

/**
 * POST /api/admin/smart-factory-log/holidays
 */
export const addHoliday = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { holidayDate, holidayName } = req.body;

    if (!holidayDate || !holidayName) {
      res.status(400).json({ success: false, message: "날짜와 이름은 필수입니다." });
      return;
    }

    await query(
      "INSERT INTO smart_factory_holidays (holiday_date, holiday_name) VALUES ($1, $2) ON CONFLICT (holiday_date) DO UPDATE SET holiday_name = $2",
      [holidayDate, holidayName]
    );

    res.json({ success: true, message: "공휴일이 추가되었습니다." });
  } catch (error) {
    logger.error("공휴일 추가 실패:", error);
    res.status(500).json({ success: false, message: "공휴일 추가 실패" });
  }
};

/**
 * DELETE /api/admin/smart-factory-log/holidays/:id
 */
export const deleteHoliday = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { id } = req.params;
    await query("DELETE FROM smart_factory_holidays WHERE id = $1", [id]);
    res.json({ success: true, message: "공휴일이 삭제되었습니다." });
  } catch (error) {
    logger.error("공휴일 삭제 실패:", error);
    res.status(500).json({ success: false, message: "공휴일 삭제 실패" });
  }
};

// ─── API 키 관리 ───

/**
 * GET /api/admin/smart-factory-log/api-keys
 * 전체 회사 목록 + API 키 상태 (DB키 여부, 환경변수 여부)
 */
export const getApiKeys = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const companies = await query<any>(
      `SELECT cm.company_code, cm.company_name, ak.api_key
       FROM company_mng cm
       LEFT JOIN smart_factory_api_keys ak ON ak.company_code = cm.company_code
       WHERE cm.company_code != '*'
       ORDER BY cm.company_code`
    );

    const result = companies.map((c: any) => {
      let dbKeyDecrypted: string | null = null;
      if (c.api_key) {
        try {
          dbKeyDecrypted = encryptionService.decrypt(c.api_key);
        } catch {
          dbKeyDecrypted = "(복호화 실패)";
        }
      }
      return {
        companyCode: c.company_code,
        companyName: c.company_name,
        hasDbKey: !!c.api_key,
        dbKey: dbKeyDecrypted,
        hasEnvKey: !!process.env[`SMART_FACTORY_API_KEY_${c.company_code}`],
      };
    });

    res.json({ success: true, data: result });
  } catch (error) {
    logger.error("API 키 목록 조회 실패:", error);
    res.status(500).json({ success: false, message: "API 키 목록 조회 실패" });
  }
};

/**
 * POST /api/admin/smart-factory-log/api-keys
 * API 키 저장 (암호화)
 */
export const saveApiKey = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { companyCode, apiKey } = req.body;

    if (!companyCode || !apiKey) {
      res.status(400).json({ success: false, message: "회사코드와 API 키는 필수입니다." });
      return;
    }

    const encrypted = encryptionService.encrypt(apiKey);

    await query(
      `INSERT INTO smart_factory_api_keys (company_code, api_key, updated_at)
       VALUES ($1, $2, NOW())
       ON CONFLICT (company_code) DO UPDATE SET api_key = $2, updated_at = NOW()`,
      [companyCode, encrypted]
    );

    res.json({ success: true, message: "API 키가 저장되었습니다." });
  } catch (error) {
    logger.error("API 키 저장 실패:", error);
    res.status(500).json({ success: false, message: "API 키 저장 실패" });
  }
};

/**
 * DELETE /api/admin/smart-factory-log/api-keys/:companyCode
 * API 키 삭제 (환경변수 폴백으로 전환)
 */
export const deleteApiKey = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { companyCode } = req.params;

    await query(
      "DELETE FROM smart_factory_api_keys WHERE company_code = $1",
      [companyCode]
    );

    res.json({ success: true, message: "API 키가 삭제되었습니다." });
  } catch (error) {
    logger.error("API 키 삭제 실패:", error);
    res.status(500).json({ success: false, message: "API 키 삭제 실패" });
  }
};

// ─── 즉시 전송 ───

/**
 * GET /api/admin/smart-factory-log/users/:companyCode
 * 회사별 사용자 목록 조회 (즉시 전송 대상 선택용)
 */
export const getCompanyUsers = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { companyCode } = req.params;

    const users = await query<any>(
      `SELECT user_id, user_name, dept_name
       FROM user_info
       WHERE company_code = $1 AND (status = 'active' OR status IS NULL)
       ORDER BY user_name`,
      [companyCode]
    );

    res.json({ success: true, data: users });
  } catch (error) {
    logger.error("사용자 목록 조회 실패:", error);
    res.status(500).json({ success: false, message: "사용자 목록 조회 실패" });
  }
};

/**
 * POST /api/admin/smart-factory-log/send-now
 * 선택한 사용자 즉시 전송
 * body: { companyCode, userIds: string[], timeStart?, timeEnd? }
 */
export const sendNow = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { companyCode, userIds } = req.body;

    logger.info(`=== 즉시 전송 API 호출 === companyCode=${companyCode}, userIds=${JSON.stringify(userIds)}`);

    if (!companyCode || !userIds || userIds.length === 0) {
      res.status(400).json({ success: false, message: "회사코드와 사용자를 선택해주세요." });
      return;
    }

    // 사용자 정보 조회
    const users = await query<{ user_id: string; user_name: string }>(
      `SELECT user_id, user_name FROM user_info WHERE company_code = $1 AND user_id = ANY($2)`,
      [companyCode, userIds]
    );

    logger.info(`즉시 전송 대상: ${users.length}명 (조회된 사용자: ${users.map(u => u.user_id).join(", ")})`);

    // 현재 시간으로 즉시 전송
    let success = 0;
    let fail = 0;
    const remoteAddr = req.ip || "127.0.0.1";

    for (const user of users) {
      try {
        logger.info(`즉시 전송 시작: ${user.user_id}`);
        await sendSmartFactoryLog({
          userId: user.user_id,
          userName: user.user_name,
          remoteAddr,
          useType: "접속",
          companyCode,
        });
        success++;
        logger.info(`즉시 전송 성공: ${user.user_id}`);
      } catch (e) {
        fail++;
        logger.error(`즉시 전송 실패: ${user.user_id}`, e);
      }
    }

    res.json({
      success: true,
      data: { total: users.length, success, fail },
      message: `${success}명 전송 완료${fail > 0 ? `, ${fail}명 실패` : ""}`,
    });
  } catch (error) {
    logger.error("즉시 전송 실패:", error);
    res.status(500).json({ success: false, message: "즉시 전송 실패" });
  }
};
