import { Request, Response } from "express";
import { FlowExternalDbConnectionService } from "../services/flowExternalDbConnectionService";
import {
  CreateFlowExternalDbConnectionRequest,
  UpdateFlowExternalDbConnectionRequest,
} from "../types/flow";
import logger from "../utils/logger";

/**
 * 플로우 전용 외부 DB 연결 컨트롤러
 */
export class FlowExternalDbConnectionController {
  private service: FlowExternalDbConnectionService;

  constructor() {
    this.service = new FlowExternalDbConnectionService();
  }

  /**
   * GET /api/flow/external-db-connections
   * 모든 외부 DB 연결 목록 조회
   */
  async getAll(req: Request, res: Response): Promise<void> {
    try {
      const activeOnly = req.query.activeOnly === "true";
      const connections = await this.service.findAll(activeOnly);

      res.json({
        success: true,
        data: connections,
        message: `${connections.length}개의 외부 DB 연결을 조회했습니다`,
      });
    } catch (error: any) {
      logger.error("외부 DB 연결 목록 조회 오류:", error);
      res.status(500).json({
        success: false,
        message: "외부 DB 연결 목록 조회 중 오류가 발생했습니다",
        error: error.message,
      });
    }
  }

  /**
   * GET /api/flow/external-db-connections/:id
   * 특정 외부 DB 연결 조회
   */
  async getById(req: Request, res: Response): Promise<void> {
    try {
      const id = parseInt(req.params.id);
      if (isNaN(id)) {
        res.status(400).json({
          success: false,
          message: "유효하지 않은 연결 ID입니다",
        });
        return;
      }

      const connection = await this.service.findById(id);

      if (!connection) {
        res.status(404).json({
          success: false,
          message: "외부 DB 연결을 찾을 수 없습니다",
        });
        return;
      }

      res.json({
        success: true,
        data: connection,
      });
    } catch (error: any) {
      logger.error("외부 DB 연결 조회 오류:", error);
      res.status(500).json({
        success: false,
        message: "외부 DB 연결 조회 중 오류가 발생했습니다",
        error: error.message,
      });
    }
  }

  /**
   * POST /api/flow/external-db-connections
   * 새 외부 DB 연결 생성
   */
  async create(req: Request, res: Response): Promise<void> {
    try {
      const request: CreateFlowExternalDbConnectionRequest = req.body;

      // 필수 필드 검증
      if (
        !request.name ||
        !request.dbType ||
        !request.host ||
        !request.port ||
        !request.databaseName ||
        !request.username ||
        !request.password
      ) {
        res.status(400).json({
          success: false,
          message: "필수 필드가 누락되었습니다",
        });
        return;
      }

      const userId = (req as any).user?.userId || "system";
      const connection = await this.service.create(request, userId);

      logger.info(
        `외부 DB 연결 생성: ${connection.name} (ID: ${connection.id})`
      );

      res.status(201).json({
        success: true,
        data: connection,
        message: "외부 DB 연결이 생성되었습니다",
      });
    } catch (error: any) {
      logger.error("외부 DB 연결 생성 오류:", error);
      res.status(500).json({
        success: false,
        message: "외부 DB 연결 생성 중 오류가 발생했습니다",
        error: error.message,
      });
    }
  }

  /**
   * PUT /api/flow/external-db-connections/:id
   * 외부 DB 연결 수정
   */
  async update(req: Request, res: Response): Promise<void> {
    try {
      const id = parseInt(req.params.id);
      if (isNaN(id)) {
        res.status(400).json({
          success: false,
          message: "유효하지 않은 연결 ID입니다",
        });
        return;
      }

      const request: UpdateFlowExternalDbConnectionRequest = req.body;
      const userId = (req as any).user?.userId || "system";

      const connection = await this.service.update(id, request, userId);

      if (!connection) {
        res.status(404).json({
          success: false,
          message: "외부 DB 연결을 찾을 수 없습니다",
        });
        return;
      }

      logger.info(`외부 DB 연결 수정: ${connection.name} (ID: ${id})`);

      res.json({
        success: true,
        data: connection,
        message: "외부 DB 연결이 수정되었습니다",
      });
    } catch (error: any) {
      logger.error("외부 DB 연결 수정 오류:", error);
      res.status(500).json({
        success: false,
        message: "외부 DB 연결 수정 중 오류가 발생했습니다",
        error: error.message,
      });
    }
  }

  /**
   * DELETE /api/flow/external-db-connections/:id
   * 외부 DB 연결 삭제
   */
  async delete(req: Request, res: Response): Promise<void> {
    try {
      const id = parseInt(req.params.id);
      if (isNaN(id)) {
        res.status(400).json({
          success: false,
          message: "유효하지 않은 연결 ID입니다",
        });
        return;
      }

      const success = await this.service.delete(id);

      if (!success) {
        res.status(404).json({
          success: false,
          message: "외부 DB 연결을 찾을 수 없습니다",
        });
        return;
      }

      logger.info(`외부 DB 연결 삭제: ID ${id}`);

      res.json({
        success: true,
        message: "외부 DB 연결이 삭제되었습니다",
      });
    } catch (error: any) {
      logger.error("외부 DB 연결 삭제 오류:", error);
      res.status(500).json({
        success: false,
        message: "외부 DB 연결 삭제 중 오류가 발생했습니다",
        error: error.message,
      });
    }
  }

  /**
   * POST /api/flow/external-db-connections/:id/test
   * 외부 DB 연결 테스트
   */
  async testConnection(req: Request, res: Response): Promise<void> {
    try {
      const id = parseInt(req.params.id);
      if (isNaN(id)) {
        res.status(400).json({
          success: false,
          message: "유효하지 않은 연결 ID입니다",
        });
        return;
      }

      const result = await this.service.testConnection(id);

      if (result.success) {
        logger.info(`외부 DB 연결 테스트 성공: ID ${id}`);
        res.json({
          success: true,
          message: result.message,
        });
      } else {
        logger.warn(`외부 DB 연결 테스트 실패: ID ${id} - ${result.message}`);
        res.status(400).json({
          success: false,
          message: result.message,
        });
      }
    } catch (error: any) {
      logger.error("외부 DB 연결 테스트 오류:", error);
      res.status(500).json({
        success: false,
        message: "외부 DB 연결 테스트 중 오류가 발생했습니다",
        error: error.message,
      });
    }
  }

  /**
   * GET /api/flow/external-db-connections/:id/tables
   * 외부 DB의 테이블 목록 조회
   */
  async getTables(req: Request, res: Response): Promise<void> {
    try {
      const id = parseInt(req.params.id);
      if (isNaN(id)) {
        res.status(400).json({
          success: false,
          message: "유효하지 않은 연결 ID입니다",
        });
        return;
      }

      const result = await this.service.getTables(id);

      if (result.success) {
        res.json(result);
      } else {
        res.status(400).json(result);
      }
    } catch (error: any) {
      logger.error("외부 DB 테이블 목록 조회 오류:", error);
      res.status(500).json({
        success: false,
        message: "외부 DB 테이블 목록 조회 중 오류가 발생했습니다",
        error: error.message,
      });
    }
  }

  /**
   * GET /api/flow/external-db-connections/:id/tables/:tableName/columns
   * 외부 DB 특정 테이블의 컬럼 목록 조회
   */
  async getTableColumns(req: Request, res: Response): Promise<void> {
    try {
      const id = parseInt(req.params.id);
      const tableName = req.params.tableName;

      if (isNaN(id)) {
        res.status(400).json({
          success: false,
          message: "유효하지 않은 연결 ID입니다",
        });
        return;
      }

      if (!tableName) {
        res.status(400).json({
          success: false,
          message: "테이블명이 필요합니다",
        });
        return;
      }

      const result = await this.service.getTableColumns(id, tableName);

      if (result.success) {
        res.json(result);
      } else {
        res.status(400).json(result);
      }
    } catch (error: any) {
      logger.error("외부 DB 컬럼 목록 조회 오류:", error);
      res.status(500).json({
        success: false,
        message: "외부 DB 컬럼 목록 조회 중 오류가 발생했습니다",
        error: error.message,
      });
    }
  }
}
