import { localStorageAPI, STORAGE_KEYS } from "./localStorage";

// Migration utility to copy localStorage data to backend
export async function migrateLocalStorageToBackend(customBase) {
  // Determine API base dynamically from saved settings unless overridden
  const apiSettings = (() => {
    try {
      return JSON.parse(localStorage.getItem("api_settings") || "{}");
    } catch {
      return {};
    }
  })();

  const API_BASE = (() => {
    if (customBase) return customBase;
    if (apiSettings.protocol && apiSettings.hostname) {
      const p = apiSettings.port || "";
      const portPart = p ? `:${p}` : "";
      return `${apiSettings.protocol}://${apiSettings.hostname}${portPart}/api`;
    }
    return `https://houseofprayer.ddns.net:8080/api`;
  })();

  console.log("[Migration] Upload API Base:", API_BASE);

  try {
    // Preload existing backend data to minimize duplicates
    let existingSongs = [];
    let existingProfiles = [];
    let existingPlans = [];
    try {
      console.log("[Migration] Fetching existing backend data...");
      const [songsRes, profilesRes, plansRes] = await Promise.all([
        fetch(`${API_BASE}/songs`).then((r) => (r.ok ? r.json() : [])),
        fetch(`${API_BASE}/profiles`).then((r) => (r.ok ? r.json() : [])),
        fetch(`${API_BASE}/plans`).then((r) => (r.ok ? r.json() : [])),
      ]);
      existingSongs = songsRes;
      existingProfiles = profilesRes;
      existingPlans = plansRes;
    } catch (e) {}

    const existingSongTitles = new Set(
      existingSongs.map((s) => (s.title || "").toLowerCase())
    );
    const existingProfileIds = new Set(existingProfiles.map((p) => p.id));
    const existingPlanDates = new Set(existingPlans.map((pl) => pl.date));

    // 1. Migrate Songs
    const songs = await localStorageAPI.getSongs("");
    for (const song of songs) {
      if (existingSongTitles.has((song.title || "").toLowerCase())) {
        continue;
      }
      try {
        const res = await fetch(`${API_BASE}/songs`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(song),
        });
        if (res.ok) {
        } else {
        }
      } catch (err) {}
    }

    // 2. Migrate Profiles
    const profiles = await localStorageAPI.getProfiles();
    for (const profile of profiles) {
      if (existingProfileIds.has(profile.id)) {
        continue;
      }
      try {
        const res = await fetch(`${API_BASE}/profiles`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(profile),
        });
        if (res.ok) {
        } else {
        }
      } catch (err) {}
    }

    // 3. Migrate Plans
    const plans = await localStorageAPI.getPlans();
    for (const plan of plans) {
      if (existingPlanDates.has(plan.date)) {
        continue;
      }
      try {
        const planSongs = await localStorageAPI.getPlanSongs(plan.id);
        const songsData = [];
        for (const ps of planSongs) {
          const song = await localStorageAPI.getSong(ps.song_id);
          if (song) songsData.push({ ...song, order: ps.order_index });
        }
        const res = await fetch(`${API_BASE}/plans`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ ...plan, songs: songsData }),
        });
        if (res.ok) {
        } else {
        }
      } catch (err) {}
    }

    // 4. Migrate Profile Songs
    const allProfileSongs = JSON.parse(
      localStorage.getItem(STORAGE_KEYS.PROFILE_SONGS) || "[]"
    );
    for (const ps of allProfileSongs) {
      try {
        const res = await fetch(`${API_BASE}/profiles/${ps.profile_id}/songs`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ song_id: ps.song_id }),
        });
        if (res.ok) {
        } else {
        }
      } catch (err) {
        console.error(
          `❌ Failed to migrate profile-song (profile ${ps.profile_id} song ${ps.song_id}):`,
          err
        );
      }
    }

    // 5. Migrate Profile Song Keys (array form in localStorage)
    const profileSongKeysArr = JSON.parse(
      localStorage.getItem(STORAGE_KEYS.PROFILE_SONG_KEYS) || "[]"
    );
    for (const entry of profileSongKeysArr) {
      if (!entry.profile_id || !entry.song_id || !entry.key) continue;
      try {
        const res = await fetch(
          `${API_BASE}/profiles/${entry.profile_id}/songs/${entry.song_id}/key`,
          {
            method: "PUT",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ key: entry.key }),
          }
        );
        if (res.ok) {
          console.log(
            `✅ Migrated key for profile ${entry.profile_id} song ${entry.song_id}`
          );
        } else {
          console.warn(
            `⚠️ Failed to migrate key for profile ${entry.profile_id} song ${entry.song_id}`
          );
        }
      } catch (err) {
        console.error(
          `❌ Failed to migrate key (profile ${entry.profile_id} song ${entry.song_id}):`,
          err
        );
      }
    }

    return {
      success: true,
      migrated: {
        songs: songs.length,
        profiles: profiles.length,
        plans: plans.length,
        profileSongs: allProfileSongs.length,
        keys: profileSongKeysArr.length,
      },
    };
  } catch (error) {
    return { success: false, error: error.message };
  }
}

// Sync FROM backend TO localStorage (pull down all data)
export async function syncFromBackendToLocalStorage(customBase) {
  const apiSettings = (() => {
    try {
      return JSON.parse(localStorage.getItem("api_settings") || "{}");
    } catch {
      return {};
    }
  })();

  const API_BASE = (() => {
    if (customBase) return customBase;
    if (apiSettings.protocol && apiSettings.hostname) {
      const p = apiSettings.port || "";
      const portPart = p ? `:${p}` : "";
      return `${apiSettings.protocol}://${apiSettings.hostname}${portPart}/api`;
    }
    return `https://houseofprayer.ddns.net:8080/api`;
  })();

  console.log("[Migration] Download API Base:", API_BASE);

  try {
    // 1. Sync Songs
    const songsRes = await fetch(`${API_BASE}/songs`);
    if (!songsRes.ok)
      throw new Error(`Failed to fetch songs: ${songsRes.status}`);
    const backendSongs = await songsRes.json();

    const localSongs = await localStorageAPI.getSongs("");
    const localSongIds = new Set(localSongs.map((s) => s.id));

    let songsAdded = 0;
    let songsUpdated = 0;

    for (const song of backendSongs) {
      // Fetch full song details
      try {
        const detailRes = await fetch(`${API_BASE}/songs/${song.id}`);
        if (!detailRes.ok) {
          continue;
        }
        const fullSong = await detailRes.json();

        if (!fullSong.lyrics && !fullSong.chords) {
        }

        if (localSongIds.has(fullSong.id)) {
          await localStorageAPI.updateSong(fullSong.id, fullSong);
          songsUpdated++;
        } else {
          await localStorageAPI.createSong(fullSong);
          songsAdded++;
        }
      } catch (err) {}
    }

    // 2. Sync Profiles
    const profilesRes = await fetch(`${API_BASE}/profiles`);
    if (!profilesRes.ok)
      throw new Error(`Failed to fetch profiles: ${profilesRes.status}`);
    const backendProfiles = await profilesRes.json();

    const localProfiles = await localStorageAPI.getProfiles();
    const localProfileIds = new Set(localProfiles.map((p) => p.id));

    let profilesAdded = 0;
    let profilesUpdated = 0;

    for (const profile of backendProfiles) {
      if (localProfileIds.has(profile.id)) {
        await localStorageAPI.updateProfile(profile.id, profile);
        profilesUpdated++;
      } else {
        await localStorageAPI.createProfile(profile);
        profilesAdded++;
      }
    }

    // 3. Sync Plans
    const plansRes = await fetch(`${API_BASE}/plans`);
    if (!plansRes.ok)
      throw new Error(`Failed to fetch plans: ${plansRes.status}`);
    const backendPlans = await plansRes.json();

    const localPlans = await localStorageAPI.getPlans();
    const localPlanIds = new Set(localPlans.map((p) => p.id));

    let plansAdded = 0;
    let plansUpdated = 0;

    for (const plan of backendPlans) {
      if (localPlanIds.has(plan.id)) {
        await localStorageAPI.updatePlan(plan.id, plan);
        plansUpdated++;
      } else {
        await localStorageAPI.createPlan(plan);
        plansAdded++;
      }
    }

    return {
      success: true,
      synced: {
        songs: { added: songsAdded, updated: songsUpdated },
        profiles: { added: profilesAdded, updated: profilesUpdated },
        plans: { added: plansAdded, updated: plansUpdated },
      },
    };
  } catch (error) {
    return { success: false, error: error.message };
  }
}

// Full bidirectional sync: merge localStorage and backend data
export async function fullSync(customBase) {
  // First, push local changes to backend
  const uploadResult = await migrateLocalStorageToBackend(customBase);

  // Then, pull backend changes to local
  const downloadResult = await syncFromBackendToLocalStorage(customBase);

  // Trigger page refresh to show updated data without full reload
  window.dispatchEvent(new CustomEvent("dataFullySynced"));

  // Also trigger events that the app already listens for
  window.dispatchEvent(new Event("songsChanged"));
  window.dispatchEvent(new Event("plansChanged"));

  return {
    success: uploadResult.success && downloadResult.success,
    upload: uploadResult,
    download: downloadResult,
  };
}

// Export functions to call from browser console
window.migrateData = migrateLocalStorageToBackend;
window.syncFromBackend = syncFromBackendToLocalStorage;
window.fullSync = fullSync;
