// Brand operations
const {
  getAllBrandsDb,
  getBrandByIdDb,
  getBrandByNameDb,
  createBrandDb,
  updateBrandDb,
  deleteBrandDb,
  checkBrandNameExistsDb,
} = require("../db/brand.db");

// Error code operations
const {
  getErrorCodesByBrandIdDb,
  createErrorCodeDb,
  updateErrorCodeDb,
  deleteErrorCodeDb,
} = require("../db/brand_code.db");

// Solution operations
const {
  getSolutionsByErrorCodeIdDb,
  createSolutionDb,
  updateSolutionDb,
  deleteSolutionDb,
} = require("../db/brand_code_solution.db");
const { getFileUploadByPathDb } = require("../db/file_uploads.db");
const { ErrorHandler } = require("../helpers/error");

class BrandService {
  // Get all brands
  static async getAllBrands(param) {
    try {
      const results = await getAllBrandsDb(param);

      results.data.map((element) => {});

      return results;
    } catch (error) {
      throw new ErrorHandler(error.statusCode, error.message);
    }
  }

  // Get brand by ID with complete data
  static async getBrandById(id) {
    try {
      const brand = await getBrandByIdDb(id);
      if (!brand) throw new ErrorHandler(404, "Brand not found");

      const errorCodes = await getErrorCodesByBrandIdDb(brand.brand_id);

      const errorCodesWithSolutions = await Promise.all(
        errorCodes.map(async (errorCode) => {
          const solutions = await getSolutionsByErrorCodeIdDb(
            errorCode.error_code_id
          );

          const solutionsWithFiles = await Promise.all(
            solutions.map(async (solution) => {
              let fileData = null;
              // console.log('Processing solution:', {
              //   solution_id: solution.brand_code_solution_id,
              //   path_solution: solution.path_solution,
              //   type_solution: solution.type_solution
              // });

              if (solution.path_solution && solution.type_solution !== "text") {
                fileData = await getFileUploadByPathDb(solution.path_solution);
                console.log("File data found:", fileData);
              }

              const enhancedSolution = {
                ...solution,
                file_upload_name: fileData?.file_upload_name || null,
                path_document: fileData?.path_document || null,
              };

              // console.log('Enhanced solution:', {
              //   solution_id: enhancedSolution.brand_code_solution_id,
              //   original_path_solution: enhancedSolution.path_solution,
              //   path_document: enhancedSolution.path_document,
              //   file_upload_name: enhancedSolution.file_upload_name
              // });

              return enhancedSolution;
            })
          );

          return {
            ...errorCode,
            solution: solutionsWithFiles,
          };
        })
      );

      return {
        ...brand,
        error_code: errorCodesWithSolutions,
      };
    } catch (error) {
      throw new ErrorHandler(error.statusCode, error.message);
    }
  }

  // Create brand
  static async createBrandWithFullData(data) {
    try {
      if (!data || typeof data !== "object") data = {};

      if (data.brand_name) {
        const brandExists = await checkBrandNameExistsDb(data.brand_name);
        if (brandExists) {
          throw new ErrorHandler(400, "Brand name already exists");
        }
      }

      if (
        !data.error_code ||
        !Array.isArray(data.error_code) ||
        data.error_code.length === 0
      ) {
        throw new ErrorHandler(
          400,
          "Brand must have at least 1 error code with solution"
        );
      }

      for (const errorCode of data.error_code) {
        if (
          !errorCode.solution ||
          !Array.isArray(errorCode.solution) ||
          errorCode.solution.length === 0
        ) {
          throw new ErrorHandler(
            400,
            `Error code ${errorCode.error_code} must have at least 1 solution`
          );
        }
      }

      const brandData = {
        brand_name: data.brand_name,
        brand_type: data.brand_type,
        brand_manufacture: data.brand_manufacture,
        brand_model: data.brand_model,
        is_active: data.is_active,
        created_by: data.created_by,
      };

      const createdBrand = await createBrandDb(brandData);
      if (!createdBrand) {
        throw new Error("Failed to create brand");
      }

      const brandId = createdBrand.brand_id;

      for (const errorCodeData of data.error_code) {
        const errorId = await createErrorCodeDb(brandId, {
          error_code: errorCodeData.error_code,
          error_code_name: errorCodeData.error_code_name,
          error_code_description: errorCodeData.error_code_description,
          error_code_color: errorCodeData.error_code_color,
          path_icon: errorCodeData.path_icon,
          is_active: errorCodeData.is_active,
          created_by: data.created_by,
        });

        if (!errorId) {
          throw new Error("Failed to create error code");
        }

        // Create solutions for this error code
        if (errorCodeData.solution && Array.isArray(errorCodeData.solution)) {
          for (const solutionData of errorCodeData.solution) {
            await createSolutionDb(errorId, {
              solution_name: solutionData.solution_name,
              type_solution: solutionData.type_solution,
              text_solution: solutionData.text_solution || null,
              path_solution: solutionData.path_solution || null,
              is_active: solutionData.is_active,
              created_by: data.created_by,
            });
          }
        }
      }

      return await this.getBrandById(brandId);
    } catch (error) {
      throw new ErrorHandler(500, `Bulk insert failed: ${error.message}`);
    }
  }

  // Soft delete brand by ID
  static async deleteBrand(id, userId) {
    try {
      const brandExist = await getBrandByIdDb(id);

      if (!brandExist) {
        throw new ErrorHandler(404, "Brand not found");
      }

      const result = await deleteBrandDb(id, userId);

      return result;
    } catch (error) {
      throw new ErrorHandler(error.statusCode, error.message);
    }
  }

  // Update brand
  static async updateBrandWithFullData(id, data) {
    try {
      const existingBrand = await getBrandByIdDb(id);
      if (!existingBrand) throw new ErrorHandler(404, "Brand not found");

      if (data.brand_name && data.brand_name !== existingBrand.brand_name) {
        const brandExists = await checkBrandNameExistsDb(data.brand_name, id);
        if (brandExists) {
          throw new ErrorHandler(400, "Brand name already exists");
        }
      }

      const brandData = {
        brand_name: data.brand_name,
        brand_type: data.brand_type,
        brand_manufacture: data.brand_manufacture,
        brand_model: data.brand_model,
        is_active: data.is_active,
        updated_by: data.updated_by,
      };

      await updateBrandDb(existingBrand.brand_name, brandData);

      if (data.error_code && Array.isArray(data.error_code)) {
        const existingErrorCodes = await getErrorCodesByBrandIdDb(id);
        const incomingErrorCodes = data.error_code.map((ec) => ec.error_code);

        // Create/update/delete error codes
        for (const errorCodeData of data.error_code) {
          // Check if error code already exists
          const existingEC = existingErrorCodes.find(
            (ec) => ec.error_code === errorCodeData.error_code
          );

          if (existingEC) {
            // Update existing error code using separate db function
            await updateErrorCodeDb(
              existingEC.brand_id,
              existingEC.error_code,
              {
                error_code_name: errorCodeData.error_code_name,
                error_code_description: errorCodeData.error_code_description,
                error_code_color: errorCodeData.error_code_color,
                path_icon: errorCodeData.path_icon,
                is_active: errorCodeData.is_active,
                updated_by: data.updated_by,
              }
            );

            if (
              errorCodeData.solution &&
              Array.isArray(errorCodeData.solution)
            ) {
              const existingSolutions = await getSolutionsByErrorCodeIdDb(
                existingEC.error_code_id
              );
              const incomingSolutionNames = errorCodeData.solution.map(
                (s) => s.solution_name
              );

              // Update or create solutions
              for (const solutionData of errorCodeData.solution) {
                const existingSolution = existingSolutions.find(
                  (s) => s.solution_name === solutionData.solution_name
                );

                if (existingSolution) {
                  // Update existing solution
                  await updateSolutionDb(
                    existingSolution.brand_code_solution_id,
                    {
                      solution_name: solutionData.solution_name,
                      type_solution: solutionData.type_solution,
                      text_solution: solutionData.text_solution || null,
                      path_solution: solutionData.path_solution || null,
                      is_active: solutionData.is_active,
                      updated_by: data.updated_by,
                    }
                  );
                } else {
                  // Create new solution
                  await createSolutionDb(existingEC.error_code_id, {
                    solution_name: solutionData.solution_name,
                    type_solution: solutionData.type_solution,
                    text_solution: solutionData.text_solution || null,
                    path_solution: solutionData.path_solution || null,
                    is_active: solutionData.is_active,
                    created_by: data.updated_by,
                  });
                }
              }

              // Delete solutions that are not in the incoming request
              for (const existingSolution of existingSolutions) {
                if (
                  !incomingSolutionNames.includes(
                    existingSolution.solution_name
                  )
                ) {
                  await deleteSolutionDb(
                    existingSolution.brand_code_solution_id,
                    data.updated_by
                  );
                }
              }
            }
          } else {
            const errorId = await createErrorCodeDb(id, {
              error_code: errorCodeData.error_code,
              error_code_name: errorCodeData.error_code_name,
              error_code_description: errorCodeData.error_code_description,
              error_code_color: errorCodeData.error_code_color,
              path_icon: errorCodeData.path_icon,
              is_active: errorCodeData.is_active,
              created_by: data.updated_by,
            });

            if (
              errorCodeData.solution &&
              Array.isArray(errorCodeData.solution)
            ) {
              for (const solutionData of errorCodeData.solution) {
                await createSolutionDb(errorId, {
                  solution_name: solutionData.solution_name,
                  type_solution: solutionData.type_solution,
                  text_solution: solutionData.text_solution || null,
                  path_solution: solutionData.path_solution || null,
                  is_active: solutionData.is_active,
                  created_by: data.updated_by,
                });
              }
            }
          }
        }

        for (const existingEC of existingErrorCodes) {
          if (!incomingErrorCodes.includes(existingEC.error_code)) {
            await deleteErrorCodeDb(id, existingEC.error_code, data.updated_by);
          }
        }
      }

      return await this.getBrandById(id);
    } catch (error) {
      throw new ErrorHandler(500, `Update failed: ${error.message}`);
    }
  }
}

module.exports = BrandService;
