const { withXcodeProject } = require('@expo/config-plugins');
const fs = require('fs');
const path = require('path');

/**
 * Recursively copy a directory or file
 */
function copyRecursive(src, dest) {
  const stat = fs.statSync(src);
  
  if (stat.isDirectory()) {
    if (!fs.existsSync(dest)) {
      fs.mkdirSync(dest, { recursive: true });
    }
    const entries = fs.readdirSync(src);
    for (const entry of entries) {
      copyRecursive(path.join(src, entry), path.join(dest, entry));
    }
  } else {
    fs.copyFileSync(src, dest);
  }
}

/**
 * withDepthModel - Expo config plugin to bundle Core ML model into iOS app
 */
const withDepthModel = (config, { modelPath }) => {
  return withXcodeProject(config, async (config) => {
    const project = config.modResults;
    const projectRoot = config.modRequest.projectRoot;
    const platformProjectRoot = config.modRequest.platformProjectRoot;
    const projectName = config.modRequest.projectName;
    
    const sourcePath = path.join(projectRoot, modelPath);
    const fileName = path.basename(modelPath);
    
    // Copy directly to ios/ folder (main group level)
    const destPath = path.join(platformProjectRoot, fileName);
    
    console.log(`[withDepthModel] Source: ${sourcePath}`);
    console.log(`[withDepthModel] Destination: ${destPath}`);
    console.log(`[withDepthModel] Project name: ${projectName}`);
    
    if (!fs.existsSync(sourcePath)) {
      console.warn(`[withDepthModel] Model not found at ${sourcePath}`);
      return config;
    }
    
    // Copy the model bundle
    try {
      if (fs.existsSync(destPath)) {
        fs.rmSync(destPath, { recursive: true, force: true });
      }
      copyRecursive(sourcePath, destPath);
      console.log(`[withDepthModel] Copied ${fileName} to ${destPath}`);
    } catch (error) {
      console.error(`[withDepthModel] Copy failed:`, error);
      throw error;
    }
    
    // Add to Xcode project
    try {
      const target = project.getFirstTarget();
      if (!target) {
        throw new Error('No target found');
      }

      // Check if already added
      const pbxFileRef = project.pbxFileReferenceSection();
      for (const key in pbxFileRef) {
        const ref = pbxFileRef[key];
        if (ref && ref.path && (ref.path === fileName || ref.path.includes(fileName))) {
          console.log(`[withDepthModel] ${fileName} already in project`);
          return config;
        }
      }
      
      // Generate UUIDs
      const fileRefUuid = project.generateUuid();
      const buildFileUuid = project.generateUuid();
      
      console.log(`[withDepthModel] FileRef UUID: ${fileRefUuid}`);
      console.log(`[withDepthModel] BuildFile UUID: ${buildFileUuid}`);
      
      // 1. Add PBXFileReference
      // For compiled CoreML models, use wrapper.mlmodelc type
      project.pbxFileReferenceSection()[fileRefUuid] = {
        isa: 'PBXFileReference',
        lastKnownFileType: 'wrapper.mlmodelc',
        name: fileName,
        path: fileName,
        sourceTree: '"<group>"',
      };
      project.pbxFileReferenceSection()[`${fileRefUuid}_comment`] = fileName;
      console.log(`[withDepthModel] Added PBXFileReference`);
      
      // 2. Add PBXBuildFile
      project.pbxBuildFileSection()[buildFileUuid] = {
        isa: 'PBXBuildFile',
        fileRef: fileRefUuid,
        fileRef_comment: fileName,
      };
      project.pbxBuildFileSection()[`${buildFileUuid}_comment`] = `${fileName} in Resources`;
      console.log(`[withDepthModel] Added PBXBuildFile`);
      
      // 3. Add to main group (since file is in ios/ directly)
      const mainGroupUuid = project.getFirstProject().firstProject.mainGroup;
      const groups = project.hash.project.objects['PBXGroup'];
      const mainGroup = groups[mainGroupUuid];
      
      if (mainGroup && mainGroup.children) {
        mainGroup.children.push({
          value: fileRefUuid,
          comment: fileName,
        });
        console.log(`[withDepthModel] Added to main group: ${mainGroupUuid}`);
      } else {
        throw new Error('Could not find main group');
      }
      
      // 4. Add to PBXResourcesBuildPhase
      const nativeTargets = project.hash.project.objects['PBXNativeTarget'];
      let addedToResources = false;
      
      for (const targetKey in nativeTargets) {
        if (targetKey.endsWith('_comment')) continue;
        const nativeTarget = nativeTargets[targetKey];
        if (!nativeTarget || !nativeTarget.buildPhases) continue;
        
        for (const phase of nativeTarget.buildPhases) {
          const phaseUuid = phase.value || phase;
          const resourcesPhases = project.hash.project.objects['PBXResourcesBuildPhase'];
          
          if (resourcesPhases && resourcesPhases[phaseUuid]) {
            const resourcesPhase = resourcesPhases[phaseUuid];
            if (resourcesPhase.files) {
              resourcesPhase.files.push({
                value: buildFileUuid,
                comment: `${fileName} in Resources`,
              });
              console.log(`[withDepthModel] Added to PBXResourcesBuildPhase: ${phaseUuid}`);
              addedToResources = true;
              break;
            }
          }
        }
        if (addedToResources) break;
      }
      
      if (!addedToResources) {
        throw new Error('Could not add to Resources build phase');
      }
      
      console.log(`[withDepthModel] Successfully configured ${fileName} in Xcode project`);
      
    } catch (error) {
      console.error(`[withDepthModel] Error:`, error.message);
      throw error;
    }
    
    return config;
  });
};

module.exports = withDepthModel;
