import { getPool } from "../database/db";

export class YardLayoutService {
  // 모든 야드 레이아웃 목록 조회
  async getAllLayouts() {
    const query = `
      SELECT 
        yl.id,
        yl.name,
        yl.description,
        yl.created_by,
        yl.created_at,
        yl.updated_at,
        COUNT(ymp.id) as placement_count
      FROM yard_layout yl
      LEFT JOIN yard_material_placement ymp ON yl.id = ymp.yard_layout_id
      GROUP BY yl.id
      ORDER BY yl.updated_at DESC
    `;

    const pool = getPool();
    const result = await pool.query(query);
    return result.rows;
  }

  // 특정 야드 레이아웃 상세 조회
  async getLayoutById(id: number) {
    const query = `
      SELECT 
        id,
        name,
        description,
        created_by,
        created_at,
        updated_at
      FROM yard_layout
      WHERE id = $1
    `;

    const pool = getPool();
    const result = await pool.query(query, [id]);
    return result.rows[0] || null;
  }

  // 새 야드 레이아웃 생성
  async createLayout(data: {
    name: string;
    description?: string;
    created_by?: string;
  }) {
    const query = `
      INSERT INTO yard_layout (name, description, created_by)
      VALUES ($1, $2, $3)
      RETURNING *
    `;

    const pool = getPool();
    const result = await pool.query(query, [
      data.name,
      data.description || null,
      data.created_by || null,
    ]);
    return result.rows[0];
  }

  // 야드 레이아웃 수정 (이름, 설명만)
  async updateLayout(
    id: number,
    data: { name?: string; description?: string }
  ) {
    const query = `
      UPDATE yard_layout
      SET 
        name = COALESCE($1, name),
        description = COALESCE($2, description),
        updated_at = CURRENT_TIMESTAMP
      WHERE id = $3
      RETURNING *
    `;

    const pool = getPool();
    const result = await pool.query(query, [
      data.name || null,
      data.description || null,
      id,
    ]);
    return result.rows[0] || null;
  }

  // 야드 레이아웃 삭제
  async deleteLayout(id: number) {
    const query = `DELETE FROM yard_layout WHERE id = $1 RETURNING *`;
    const pool = getPool();
    const result = await pool.query(query, [id]);
    return result.rows[0] || null;
  }

  // 특정 야드의 모든 배치 자재 조회
  async getPlacementsByLayoutId(layoutId: number) {
    const query = `
      SELECT 
        id,
        yard_layout_id,
        material_code,
        material_name,
        quantity,
        unit,
        position_x,
        position_y,
        position_z,
        size_x,
        size_y,
        size_z,
        color,
        data_source_type,
        data_source_config,
        data_binding,
        memo,
        created_at,
        updated_at
      FROM yard_material_placement
      WHERE yard_layout_id = $1
      ORDER BY created_at ASC
    `;

    const pool = getPool();
    const result = await pool.query(query, [layoutId]);
    return result.rows;
  }

  // 야드에 자재 배치 추가 (빈 요소 또는 설정된 요소)
  async addMaterialPlacement(layoutId: number, data: any) {
    const query = `
      INSERT INTO yard_material_placement (
        yard_layout_id,
        material_code,
        material_name,
        quantity,
        unit,
        position_x,
        position_y,
        position_z,
        size_x,
        size_y,
        size_z,
        color,
        data_source_type,
        data_source_config,
        data_binding,
        memo
      ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
      RETURNING *
    `;

    const pool = getPool();

    // NaN 방지를 위한 안전한 변환 함수
    const safeParseInt = (
      value: any,
      defaultValue: number | null = null
    ): number | null => {
      if (!value && value !== 0) return defaultValue;
      const parsed = parseInt(String(value), 10);
      return isNaN(parsed) ? defaultValue : parsed;
    };

    const safeParseFloat = (value: any, defaultValue: number): number => {
      if (!value && value !== 0) return defaultValue;
      const parsed = parseFloat(String(value));
      return isNaN(parsed) ? defaultValue : parsed;
    };

    const result = await pool.query(query, [
      layoutId,
      data.material_code || null,
      data.material_name || null,
      safeParseInt(data.quantity, null),
      data.unit || null,
      safeParseFloat(data.position_x, 0),
      safeParseFloat(data.position_y, 0),
      safeParseFloat(data.position_z, 0),
      safeParseFloat(data.size_x, 5),
      safeParseFloat(data.size_y, 5),
      safeParseFloat(data.size_z, 5),
      data.color || "#9ca3af", // 미설정 시 회색
      data.data_source_type || null,
      data.data_source_config ? JSON.stringify(data.data_source_config) : null,
      data.data_binding ? JSON.stringify(data.data_binding) : null,
      data.memo || null,
    ]);

    return result.rows[0];
  }

  // 배치 정보 수정 (위치, 크기, 색상, 데이터 바인딩 등)
  async updatePlacement(placementId: number, data: any) {
    const query = `
      UPDATE yard_material_placement
      SET 
        material_code = COALESCE($1, material_code),
        material_name = COALESCE($2, material_name),
        quantity = COALESCE($3, quantity),
        unit = COALESCE($4, unit),
        position_x = COALESCE($5, position_x),
        position_y = COALESCE($6, position_y),
        position_z = COALESCE($7, position_z),
        size_x = COALESCE($8, size_x),
        size_y = COALESCE($9, size_y),
        size_z = COALESCE($10, size_z),
        color = COALESCE($11, color),
        data_source_type = COALESCE($12, data_source_type),
        data_source_config = COALESCE($13, data_source_config),
        data_binding = COALESCE($14, data_binding),
        memo = COALESCE($15, memo),
        updated_at = CURRENT_TIMESTAMP
      WHERE id = $16
      RETURNING *
    `;

    const pool = getPool();

    // NaN 방지를 위한 안전한 변환 함수
    const safeParseInt = (value: any): number | null => {
      if (value === null || value === undefined) return null;
      const parsed = parseInt(String(value), 10);
      return isNaN(parsed) ? null : parsed;
    };

    const safeParseFloat = (value: any): number | null => {
      if (value === null || value === undefined) return null;
      const parsed = parseFloat(String(value));
      return isNaN(parsed) ? null : parsed;
    };

    const result = await pool.query(query, [
      data.material_code !== undefined ? data.material_code : null,
      data.material_name !== undefined ? data.material_name : null,
      data.quantity !== undefined ? safeParseInt(data.quantity) : null,
      data.unit !== undefined ? data.unit : null,
      data.position_x !== undefined ? safeParseFloat(data.position_x) : null,
      data.position_y !== undefined ? safeParseFloat(data.position_y) : null,
      data.position_z !== undefined ? safeParseFloat(data.position_z) : null,
      data.size_x !== undefined ? safeParseFloat(data.size_x) : null,
      data.size_y !== undefined ? safeParseFloat(data.size_y) : null,
      data.size_z !== undefined ? safeParseFloat(data.size_z) : null,
      data.color !== undefined ? data.color : null,
      data.data_source_type !== undefined ? data.data_source_type : null,
      data.data_source_config !== undefined
        ? JSON.stringify(data.data_source_config)
        : null,
      data.data_binding !== undefined
        ? JSON.stringify(data.data_binding)
        : null,
      data.memo !== undefined ? data.memo : null,
      placementId,
    ]);

    return result.rows[0] || null;
  }

  // 배치 해제 (자재는 삭제되지 않음)
  async removePlacement(placementId: number) {
    const query = `DELETE FROM yard_material_placement WHERE id = $1 RETURNING *`;
    const pool = getPool();
    const result = await pool.query(query, [placementId]);
    return result.rows[0] || null;
  }

  // 여러 배치 일괄 업데이트
  async batchUpdatePlacements(layoutId: number, placements: any[]) {
    const pool = getPool();
    const client = await pool.connect();

    try {
      await client.query("BEGIN");

      const results = [];
      for (const placement of placements) {
        const query = `
          UPDATE yard_material_placement
          SET 
            position_x = $1,
            position_y = $2,
            position_z = $3,
            size_x = $4,
            size_y = $5,
            size_z = $6,
            color = $7,
            updated_at = CURRENT_TIMESTAMP
          WHERE id = $8 AND yard_layout_id = $9
          RETURNING *
        `;

        const result = await client.query(query, [
          placement.position_x,
          placement.position_y,
          placement.position_z,
          placement.size_x,
          placement.size_y,
          placement.size_z,
          placement.color,
          placement.id,
          layoutId,
        ]);

        if (result.rows[0]) {
          results.push(result.rows[0]);
        }
      }

      await client.query("COMMIT");
      return results;
    } catch (error) {
      await client.query("ROLLBACK");
      throw error;
    } finally {
      client.release();
    }
  }

  // 야드 레이아웃 복제
  async duplicateLayout(id: number, newName: string) {
    const pool = getPool();
    const client = await pool.connect();

    try {
      await client.query("BEGIN");

      // 원본 레이아웃 조회
      const layoutQuery = `SELECT * FROM yard_layout WHERE id = $1`;
      const layoutResult = await client.query(layoutQuery, [id]);
      const originalLayout = layoutResult.rows[0];

      if (!originalLayout) {
        throw new Error("Layout not found");
      }

      // 새 레이아웃 생성
      const newLayoutQuery = `
        INSERT INTO yard_layout (name, description, created_by)
        VALUES ($1, $2, $3)
        RETURNING *
      `;
      const newLayoutResult = await client.query(newLayoutQuery, [
        newName,
        originalLayout.description,
        originalLayout.created_by,
      ]);
      const newLayout = newLayoutResult.rows[0];

      // 배치 자재 복사
      const placementsQuery = `SELECT * FROM yard_material_placement WHERE yard_layout_id = $1`;
      const placementsResult = await client.query(placementsQuery, [id]);

      for (const placement of placementsResult.rows) {
        await client.query(
          `
          INSERT INTO yard_material_placement (
            yard_layout_id, material_code, material_name,
            quantity, unit, position_x, position_y, position_z,
            size_x, size_y, size_z, color, 
            data_source_type, data_source_config, data_binding, memo
          ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
        `,
          [
            newLayout.id,
            placement.material_code,
            placement.material_name,
            placement.quantity,
            placement.unit,
            placement.position_x,
            placement.position_y,
            placement.position_z,
            placement.size_x,
            placement.size_y,
            placement.size_z,
            placement.color,
            placement.data_source_type,
            placement.data_source_config,
            placement.data_binding,
            placement.memo,
          ]
        );
      }

      await client.query("COMMIT");
      return newLayout;
    } catch (error) {
      await client.query("ROLLBACK");
      throw error;
    } finally {
      client.release();
    }
  }
}

export default new YardLayoutService();
