import {
  createApplicationSchema,
  updateApplicationSchema,
  normalizeApplicationPayload,
} from "../models/application.schema.js";
import {
  listApplications,
  getApplicationById,
  createApplication,
  updateApplication,
  deleteApplication,
} from "../services/applications.service.js";
import { successResponse, errorResponse } from "../utils/response.js";
import { HTTP_STATUS } from "../constants/index.js";
import logger from "../utils/logger.js";

export const list = async (req, res, next) => {
  try {
    const filters = {
      status: req.query.status,
      jobId: req.query.jobId,
    };
    const items = await listApplications(filters);
    return successResponse(res, items, HTTP_STATUS.OK);
  } catch (err) {
    logger.error("Error listing applications:", err);
    next(err);
  }
};

export const getById = async (req, res, next) => {
  try {
    const { id } = req.params;
    if (!id) {
      return errorResponse(res, "Application ID is required", HTTP_STATUS.BAD_REQUEST);
    }
    const item = await getApplicationById(id);
    if (!item) {
      return errorResponse(res, "Application not found", HTTP_STATUS.NOT_FOUND);
    }
    return successResponse(res, item, HTTP_STATUS.OK);
  } catch (err) {
    logger.error("Error getting application by ID:", err);
    next(err);
  }
};

export const create = async (req, res, next) => {
  try {
    logger.info("Received application creation request");
    logger.info("Request body:", req.body);
    logger.info("Request file:", req.file ? { 
      filename: req.file.filename, 
      path: req.file.path, 
      size: req.file.size,
      mimetype: req.file.mimetype
    } : "No file");

    // Check for file validation errors from multer
    if (req.fileValidationError) {
      logger.warn("File validation error:", req.fileValidationError);
      return errorResponse(res, req.fileValidationError, HTTP_STATUS.BAD_REQUEST);
    }

    // Extract form data
    const { fullName, email, phone, jobId, role, location, note } = req.body;

    // Validate required fields
    if (!fullName || !email || !role || !location) {
      logger.warn("Missing required fields:", { fullName: !!fullName, email: !!email, role: !!role, location: !!location });
      return errorResponse(
        res,
        "Missing required fields: fullName, email, role, and location are required",
        HTTP_STATUS.BAD_REQUEST
      );
    }

    // Handle jobId - if it's "general" or empty, set to null
    let finalJobId = null;
    if (jobId && jobId !== "general" && jobId.trim() !== "") {
      finalJobId = jobId.trim();
      // Validate if it's a valid MongoDB ObjectId format
      if (!/^[0-9a-fA-F]{24}$/.test(finalJobId)) {
        logger.warn("Invalid jobId format:", finalJobId);
        finalJobId = null; // Treat invalid ObjectId as null
      }
    }

    // Check if file is uploaded
    if (!req.file) {
      logger.warn("No file uploaded in request");
      return errorResponse(
        res,
        "CV/Resume file is required",
        HTTP_STATUS.BAD_REQUEST
      );
    }

    // Upload file to Cloudinary
    let resumeUrl;
    try {
      const { uploadToCloudinary } = await import("../utils/cloudinary.js");
      const filePath = req.file.path;
      logger.info(`Attempting to upload file: ${filePath}`);
      
      resumeUrl = await uploadToCloudinary(filePath, "aibit_soft/resumes");
      logger.info(`Successfully uploaded to Cloudinary: ${resumeUrl}`);
    } catch (cloudinaryError) {
      logger.error("Cloudinary upload error:", cloudinaryError);
      
      // Delete local file if Cloudinary upload fails
      if (req.file && req.file.path) {
        const { unlink } = await import("fs/promises");
        try {
          await unlink(req.file.path);
          logger.info(`Deleted local file after Cloudinary error: ${req.file.path}`);
        } catch (err) {
          logger.warn("Failed to delete file after Cloudinary error:", err);
        }
      }
      
      const errorMessage = cloudinaryError?.message || "Failed to upload CV. Please try again.";
      return errorResponse(
        res,
        errorMessage.includes("credentials") 
          ? "Cloudinary is not configured. Please contact administrator."
          : errorMessage,
        HTTP_STATUS.INTERNAL_SERVER_ERROR
      );
    }

    // Prepare data for database
    const applicationData = {
      fullName: fullName.trim(),
      email: email.trim().toLowerCase(),
      phone: phone ? phone.trim() : undefined,
      jobId: finalJobId,
      role: role.trim(),
      location: location.trim(),
      resumeUrl: resumeUrl,
      note: note ? note.trim() : undefined,
      status: "New",
    };

    // Validate data
    const normalized = normalizeApplicationPayload(applicationData);
    logger.info("Normalized application data:", normalized);
    
    const parsed = createApplicationSchema.safeParse(normalized);
    if (!parsed.success) {
      logger.error("Schema validation failed:", parsed.error.flatten());
      return errorResponse(
        res,
        "Validation failed: " + JSON.stringify(parsed.error.flatten().fieldErrors),
        HTTP_STATUS.BAD_REQUEST,
        parsed.error.flatten()
      );
    }

    logger.info("Creating application with data:", parsed.data);
    const created = await createApplication(parsed.data);
    logger.info(`Application created successfully with ID: ${created._id}`);
    return successResponse(res, created, HTTP_STATUS.CREATED);
  } catch (err) {
    logger.error("Error creating application:", err);
    logger.error("Error stack:", err.stack);
    // Return more detailed error message
    const errorMessage = err.message || "Internal server error";
    return errorResponse(
      res,
      `Failed to create application: ${errorMessage}`,
      HTTP_STATUS.INTERNAL_SERVER_ERROR
    );
  }
};

export const update = async (req, res, next) => {
  try {
    const { id } = req.params;
    if (!id) {
      return errorResponse(res, "Application ID is required", HTTP_STATUS.BAD_REQUEST);
    }
    const normalized = normalizeApplicationPayload(req.body);
    const parsed = updateApplicationSchema.safeParse(normalized);
    if (!parsed.success) {
      return errorResponse(
        res,
        "Validation failed",
        HTTP_STATUS.BAD_REQUEST,
        parsed.error.flatten()
      );
    }
    const updated = await updateApplication(id, parsed.data);
    if (!updated) {
      return errorResponse(res, "Application not found", HTTP_STATUS.NOT_FOUND);
    }
    logger.info(`Application updated with ID: ${id}`);
    return successResponse(res, updated, HTTP_STATUS.OK);
  } catch (err) {
    logger.error("Error updating application:", err);
    next(err);
  }
};

export const remove = async (req, res, next) => {
  try {
    const { id } = req.params;
    if (!id) {
      return errorResponse(res, "Application ID is required", HTTP_STATUS.BAD_REQUEST);
    }
    const ok = await deleteApplication(id);
    if (!ok) {
      return errorResponse(res, "Application not found", HTTP_STATUS.NOT_FOUND);
    }
    logger.info(`Application deleted with ID: ${id}`);
    return res.status(HTTP_STATUS.NO_CONTENT).send();
  } catch (err) {
    logger.error("Error deleting application:", err);
    next(err);
  }
};

