import i18next from "i18next";
import { ItemView, Notice, WorkspaceLeaf, TFile } from "obsidian";
import type HaloPlugin from "../main";

export const SYNC_STATUS_VIEW_TYPE = "halo-sync-status";

type SyncAction = "publish" | "update" | "pull" | "delete";

interface SyncHistoryItem {
  id: string;
  action: SyncAction;
  title: string;
  timestamp: number;
  success: boolean;
}

type SyncStatus = "synced" | "local-modified" | "remote-updated" | "unpublished";

interface PostItem {
  file: TFile;
  title: string;
  slug: string;
  haloName: string;
  haloSite: string;
  publishStatus: boolean;
  syncStatus: SyncStatus;
  categories: string[];
  tags: string[];
  localModified?: number;
  remoteModified?: number;
}

interface GroupedPosts {
  category: string;
  posts: PostItem[];
}

export class SyncStatusView extends ItemView {
  private plugin: HaloPlugin;
  private history: SyncHistoryItem[] = [];
  private selectedPosts: Set<string> = new Set();
  private searchQuery: string = "";
  private filterMode: "all" | "synced" | "pending" = "all";

  constructor(leaf: WorkspaceLeaf, plugin: HaloPlugin) {
    super(leaf);
    this.plugin = plugin;
    this.loadHistory();
  }

  getViewType(): string {
    return SYNC_STATUS_VIEW_TYPE;
  }

  getDisplayText(): string {
    return i18next.t("sync_panel.title");
  }

  async onOpen() {
    this.render();
  }

  private loadHistory() {
    const stored = this.plugin.loadData();
    this.history = stored?.syncHistory || [];
  }

  private saveHistory() {
    const data = this.plugin.loadData() || {};
    data.syncHistory = this.history.slice(-50);
    this.plugin.saveData(data);
  }

  addToHistory(action: SyncAction, title: string, success: boolean) {
    this.history.push({
      id: Date.now().toString(),
      action,
      title,
      timestamp: Date.now(),
      success,
    });
    this.saveHistory();
  }

  private getPublishedPosts(): PostItem[] {
    const posts: PostItem[] = [];

    for (const file of this.plugin.app.vault.getFiles()) {
      if (file.extension !== "md") continue;

      const cache = this.plugin.app.metadataCache.getFileCache(file);
      if (!cache?.frontmatter?.halo?.name) continue;

      const haloPublish = cache.frontmatter.halo.publish ?? false;
      const localModified = cache.frontmatter.halo.localModified ?? false;

      let syncStatus: SyncStatus = "synced";
      if (!haloPublish) {
        syncStatus = "unpublished";
      } else if (localModified) {
        syncStatus = "local-modified";
      }

      const categories = this.extractCategories(cache.frontmatter);

      posts.push({
        file,
        title: cache.frontmatter.title || file.basename,
        slug: cache.frontmatter.slug || "",
        haloName: cache.frontmatter.halo.name,
        haloSite: cache.frontmatter.halo.site || "",
        publishStatus: haloPublish,
        syncStatus,
        categories,
        tags: this.extractTags(cache.frontmatter),
        localModified: file.stat.mtime,
        remoteModified: cache.frontmatter.halo.remoteModified,
      });
    }

    return posts;
  }

  private extractCategories(frontmatter: Record<string, unknown>): string[] {
    const categories: string[] = [];
    if (frontmatter.categories) {
      if (Array.isArray(frontmatter.categories)) {
        categories.push(...frontmatter.categories.map(String));
      } else {
        categories.push(String(frontmatter.categories));
      }
    }
    return categories.length > 0 ? categories : ["未分类"];
  }

  private extractTags(frontmatter: Record<string, unknown>): string[] {
    const tags: string[] = [];
    if (frontmatter.tags) {
      if (Array.isArray(frontmatter.tags)) {
        tags.push(...frontmatter.tags.map(String));
      } else if (typeof frontmatter.tags === "string") {
        const parsed = frontmatter.tags.replace(/[\[\]]/g, "").split(",").map((t: string) => t.trim());
        tags.push(...parsed.filter(Boolean));
      }
    }
    return tags;
  }

  private groupPostsByCategory(posts: PostItem[]): GroupedPosts[] {
    const groups = new Map<string, PostItem[]>();

    for (const post of posts) {
      const category = post.categories[0] || "未分类";
      if (!groups.has(category)) {
        groups.set(category, []);
      }
      groups.get(category)!.push(post);
    }

    return Array.from(groups.entries())
      .map(([category, posts]) => ({ category, posts }))
      .sort((a, b) => {
        if (a.category === "未分类") return 1;
        if (b.category === "未分类") return -1;
        return a.category.localeCompare(b.category);
      });
  }

  private filterPosts(posts: PostItem[]): PostItem[] {
    let filtered = posts;

    if (this.searchQuery) {
      const query = this.searchQuery.toLowerCase();
      filtered = filtered.filter(
        (p) =>
          p.title.toLowerCase().includes(query) ||
          p.slug.toLowerCase().includes(query) ||
          p.categories.some((c) => c.toLowerCase().includes(query)) ||
          p.tags.some((t) => t.toLowerCase().includes(query))
      );
    }

    switch (this.filterMode) {
      case "synced":
        return filtered.filter((p) => p.syncStatus === "synced");
      case "pending":
        return filtered.filter((p) => p.syncStatus !== "synced");
      default:
        return filtered;
    }
  }

  private getStatusIcon(status: SyncStatus): string {
    switch (status) {
      case "synced":
        return "🟢";
      case "local-modified":
        return "🟡";
      case "remote-updated":
        return "🔵";
      case "unpublished":
        return "⚪";
    }
  }

  private getStatusText(status: SyncStatus): string {
    switch (status) {
      case "synced":
        return i18next.t("sync_panel.status_synced");
      case "local-modified":
        return i18next.t("sync_panel.status_local_modified");
      case "remote-updated":
        return i18next.t("sync_panel.status_remote_updated");
      case "unpublished":
        return i18next.t("sync_panel.status_unpublished");
    }
  }

  private formatRelativeTime(timestamp: number): string {
    const diff = Date.now() - timestamp;
    const minutes = Math.floor(diff / 60000);
    const hours = Math.floor(diff / 3600000);
    const days = Math.floor(diff / 86400000);

    if (minutes < 1) return i18next.t("sync_panel.time_just_now");
    if (minutes < 60) return i18next.t("sync_panel.time_minutes_ago", { count: minutes });
    if (hours < 24) return i18next.t("sync_panel.time_hours_ago", { count: hours });
    return i18next.t("sync_panel.time_days_ago", { count: days });
  }

  private async performAction(post: PostItem, action: "update" | "publish" | "pull") {
    const site = this.plugin.settings.sites.find((s) => s.url === post.haloSite);
    if (!site) {
      new Notice(i18next.t("service.error_site_not_match"));
      return;
    }

    const { default: HaloService } = await import("../service");
    const service = new HaloService(this.plugin.app, this.plugin.settings, site);

    try {
      switch (action) {
        case "update":
          await service.updatePost();
          this.addToHistory("update", post.title, true);
          new Notice(i18next.t("command.update_post.success"));
          break;
        case "publish":
          await service.publishPost();
          this.addToHistory("publish", post.title, true);
          new Notice(i18next.t("service.notice_publish_success"));
          break;
        case "pull":
          await service.pullPost(post.haloName);
          this.addToHistory("pull", post.title, true);
          break;
      }
      this.render();
    } catch {
      this.addToHistory(action, post.title, false);
      new Notice(i18next.t("service.error_publish_failed"));
    }
  }

  private renderPostDetail(post: PostItem): void {
    const modal = document.createElement("div");
    modal.className = "sync-detail-modal";
    modal.style.cssText = `
      position: fixed; top: 0; left: 0; right: 0; bottom: 0;
      background: rgba(0,0,0,0.6); display: flex; align-items: center;
      justify-content: center; z-index: 1000;
    `;

    const content = document.createElement("div");
    content.className = "sync-detail-content";
    content.style.cssText = `
      background: var(--background-primary);
      border: 1px solid var(--border-color);
      border-radius: 12px;
      width: 480px;
      max-height: 80vh;
      overflow-y: auto;
      box-shadow: 0 8px 32px rgba(0,0,0,0.3);
      padding: 24px;
    `;

    const title = document.createElement("h3");
    title.textContent = i18next.t("sync_panel.detail_title");
    title.style.cssText = "margin: 0 0 16px 0;";
    content.appendChild(title);

    const statusBadge = document.createElement("div");
    statusBadge.style.cssText = `
      display: inline-flex; align-items: center; gap: 6px;
      padding: 4px 12px; border-radius: 16px;
      background: var(--background-secondary);
      font-size: 12px; margin-bottom: 16px;
    `;
    statusBadge.textContent = `${this.getStatusIcon(post.syncStatus)} ${this.getStatusText(post.syncStatus)}`;
    content.appendChild(statusBadge);

    const infoTable = document.createElement("div");
    infoTable.style.cssText = "display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px;";

    const addRow = (label: string, value: string) => {
      const row = document.createElement("div");
      row.style.cssText = "display: flex; justify-content: space-between;";
      row.innerHTML = `<span style="color: var(--text-muted)">${label}</span><span>${value}</span>`;
      infoTable.appendChild(row);
    };

    addRow(i18next.t("sync_panel.detail_title_label"), post.title);
    addRow("Slug", post.slug || "-");
    addRow(i18next.t("sync_panel.detail_category"), post.categories.join(" > "));
    addRow(i18next.t("sync_panel.detail_tags"), post.tags.length > 0 ? post.tags.map((t) => `#${t}`).join(" ") : "-");

    content.appendChild(infoTable);

    if (post.localModified) {
      const localSection = document.createElement("div");
      localSection.style.cssText = "background: var(--background-secondary); padding: 12px; border-radius: 8px; margin-bottom: 12px;";
      localSection.innerHTML = `
        <div style="font-weight: 600; margin-bottom: 4px;">${i18next.t("sync_panel.detail_local_version")}</div>
        <div style="font-size: 12px; color: var(--text-muted);">${i18next.t("sync_panel.detail_modified")}: ${this.formatRelativeTime(post.localModified)}</div>
      `;
      content.appendChild(localSection);
    }

    const closeBtn = document.createElement("button");
    closeBtn.textContent = i18next.t("common.button_close");
    closeBtn.style.cssText = "width: 100%; margin-top: 16px; padding: 10px;";
    closeBtn.addEventListener("click", () => {
      modal.remove();
      this.render();
    });
    content.appendChild(closeBtn);

    modal.addEventListener("click", (e) => {
      if (e.target === modal) {
        modal.remove();
        this.render();
      }
    });

    document.body.appendChild(modal);
  }

  private render() {
    const container = this.containerEl;
    container.empty();
    this.selectedPosts.clear();

    const header = container.createDiv("sync-header");
    header.style.cssText = "display: flex; justify-content: space-between; align-items: center; padding: 16px; border-bottom: 1px solid var(--border-color);";

    const titleSection = header.createDiv("sync-title-section");
    titleSection.style.cssText = "display: flex; align-items: center; gap: 8px;";

    const statusDot = titleSection.createSpan("sync-status-dot");
    statusDot.style.cssText = "width: 10px; height: 10px; border-radius: 50%; background: var(--color-green);";

    titleSection.createEl("h2", { text: i18next.t("sync_panel.title"), cls: "sync-view-title" });

    const actions = header.createDiv("sync-actions");
    actions.style.cssText = "display: flex; gap: 8px;";

    const settingsBtn = actions.createEl("button", {
      text: "⚙️",
      cls: "sync-icon-btn",
      attr: { title: i18next.t("sync_panel.button_settings") }
    });
    settingsBtn.style.cssText = "border: none; background: transparent; cursor: pointer; font-size: 16px; padding: 4px;";
    settingsBtn.addEventListener("click", () => {
      (this.app as unknown as { settings: unknown }).settings;
    });

    const historyBtn = actions.createEl("button", {
      text: "📊",
      cls: "sync-icon-btn",
      attr: { title: i18next.t("sync_panel.button_history") }
    });
    historyBtn.style.cssText = "border: none; background: transparent; cursor: pointer; font-size: 16px; padding: 4px;";
    historyBtn.addEventListener("click", () => this.showHistory());

    const searchBar = container.createDiv("sync-search-bar");
    searchBar.style.cssText = "padding: 12px 16px; border-bottom: 1px solid var(--border-color);";

    const searchInput = searchBar.createEl("input", {
      type: "text",
      cls: "sync-search-input"
    }) as HTMLInputElement;
    searchInput.setAttribute("placeholder", i18next.t("sync_panel.search_placeholder"));
    searchInput.style.cssText = `
      width: 100%; padding: 8px 12px; border: 1px solid var(--border-color);
      border-radius: 8px; background: var(--background-secondary);
    `;
    searchInput.value = this.searchQuery;
    searchInput.addEventListener("input", () => {
      this.searchQuery = searchInput.value;
      this.render();
    });

    const filterTabs = container.createDiv("sync-filter-tabs");
    filterTabs.style.cssText = "display: flex; padding: 0 16px; gap: 8px; border-bottom: 1px solid var(--border-color);";

    const filters: Array<{ key: typeof this.filterMode; label: string }> = [
      { key: "all", label: `📁 ${i18next.t("sync_panel.filter_all")}` },
      { key: "synced", label: `✅ ${i18next.t("sync_panel.filter_synced")}` },
      { key: "pending", label: `🔄 ${i18next.t("sync_panel.filter_pending")}` },
    ];

    for (const filter of filters) {
      const tab = filterTabs.createEl("button");
      tab.textContent = filter.label;
      tab.style.cssText = `
        padding: 8px 16px; border: none; background: transparent;
        cursor: pointer; border-bottom: 2px solid transparent;
        font-size: 13px; transition: all 0.2s;
      `;
      if (this.filterMode === filter.key) {
        tab.style.borderBottomColor = "var(--interactive-accent)";
        tab.style.color = "var(--interactive-accent)";
      }
      tab.addEventListener("click", () => {
        this.filterMode = filter.key;
        this.render();
      });
    }

    const content = container.createDiv("sync-content");
    content.style.cssText = "flex: 1; overflow-y: auto; padding: 16px;";

    const posts = this.getPublishedPosts();
    const filteredPosts = this.filterPosts(posts);
    const groupedPosts = this.groupPostsByCategory(filteredPosts);

    if (filteredPosts.length === 0) {
      content.createEl("div", {
        text: posts.length === 0 ? i18next.t("sync_panel.empty") : i18next.t("sync_panel.no_results"),
        cls: "sync-empty"
      });
      return;
    }

    for (const group of groupedPosts) {
      const groupHeader = content.createDiv("sync-group-header");
      groupHeader.style.cssText = `
        display: flex; align-items: center; gap: 8px;
        padding: 8px 0; margin-bottom: 8px;
        font-weight: 600; font-size: 14px; color: var(--text-muted);
      `;
      groupHeader.createSpan({ text: "📂" });
      groupHeader.createEl("span", { text: `${group.category} (${group.posts.length})` });

      for (const post of group.posts) {
        this.renderPostCard(content, post);
      }
    }

    const stats = container.createDiv("sync-stats");
    stats.style.cssText = `
      padding: 12px 16px; border-top: 1px solid var(--border-color);
      display: flex; justify-content: space-between; font-size: 12px; color: var(--text-muted);
    `;

    const syncedCount = filteredPosts.filter((p) => p.syncStatus === "synced").length;
    const pendingCount = filteredPosts.length - syncedCount;

    stats.createEl("span", { text: i18next.t("sync_panel.stats_total", { count: filteredPosts.length }) });
    stats.createEl("span", { text: i18next.t("sync_panel.stats_synced", { count: syncedCount }) });
    stats.createEl("span", { text: i18next.t("sync_panel.stats_pending", { count: pendingCount }), cls: "sync-stats-pending" });
  }

  private renderPostCard(container: HTMLElement, post: PostItem) {
    const card = container.createDiv("sync-post-card");
    card.style.cssText = `
      background: var(--background-secondary);
      border: 1px solid var(--border-color);
      border-radius: 10px;
      padding: 14px;
      margin-bottom: 10px;
      transition: all 0.2s;
    `;

    card.addEventListener("mouseenter", () => {
      card.style.borderColor = "var(--interactive-accent)";
      card.style.boxShadow = "0 2px 8px rgba(0,0,0,0.1)";
    });
    card.addEventListener("mouseleave", () => {
      card.style.borderColor = "var(--border-color)";
      card.style.boxShadow = "none";
    });

    const cardHeader = card.createDiv("card-header");
    cardHeader.style.cssText = "display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 10px;";

    const cardTitle = cardHeader.createDiv("card-title-section");
    cardTitle.style.cssText = "display: flex; align-items: center; gap: 8px; flex: 1;";

    const checkbox = cardTitle.createEl("input", {
      type: "checkbox",
      cls: "sync-post-checkbox"
    }) as HTMLInputElement;
    checkbox.style.cssText = "width: 16px; height: 16px; cursor: pointer;";
    checkbox.checked = this.selectedPosts.has(post.haloName);
    checkbox.addEventListener("change", () => {
      if (checkbox.checked) {
        this.selectedPosts.add(post.haloName);
      } else {
        this.selectedPosts.delete(post.haloName);
      }
    });

    const statusIcon = cardTitle.createSpan("card-status-icon");
    statusIcon.style.cssText = "font-size: 16px;";
    statusIcon.setText(this.getStatusIcon(post.syncStatus));

    const titleSpan = cardTitle.createEl("span", { text: post.title, cls: "card-title" });
    titleSpan.style.cssText = "font-weight: 600; font-size: 14px;";

    const statusBadge = cardHeader.createDiv("card-status-badge");
    statusBadge.style.cssText = `
      padding: 2px 8px; border-radius: 10px;
      font-size: 11px; background: var(--background-primary);
    `;
    statusBadge.setText(this.getStatusText(post.syncStatus));

    const cardMeta = card.createDiv("card-meta");
    cardMeta.style.cssText = "font-size: 12px; color: var(--text-muted); margin-bottom: 12px; padding-left: 24px;";

    if (post.slug) {
      cardMeta.createSpan({ text: `Slug: ${post.slug}`, cls: "card-slug" });
      cardMeta.createSpan({ text: " • ", cls: "card-meta-sep" });
    }

    if (post.localModified) {
      cardMeta.createSpan({
        text: `${i18next.t("sync_panel.last_sync")}: ${this.formatRelativeTime(post.localModified)}`
      });
    }

    const tagsContainer = card.createDiv("card-tags");
    tagsContainer.style.cssText = "display: flex; flex-wrap: wrap; gap: 4px; padding-left: 24px; margin-bottom: 12px;";
    for (const tag of post.tags.slice(0, 3)) {
      const tagEl = tagsContainer.createEl("span", { text: `#${tag}`, cls: "card-tag" });
      tagEl.style.cssText = `
        padding: 2px 6px; border-radius: 4px;
        font-size: 11px; background: var(--background-primary);
      `;
    }
    if (post.tags.length > 3) {
      tagsContainer.createSpan({ text: `+${post.tags.length - 3}`, cls: "card-tag-more" });
    }

    const cardActions = card.createDiv("card-actions");
    cardActions.style.cssText = "display: flex; gap: 6px; padding-left: 24px;";

    const actionButtons: Array<{ text: string; class: string; action: () => void }> = [
      {
        text: "👁",
        class: "card-btn card-btn-preview",
        action: () => this.renderPostDetail(post),
      },
      {
        text: post.publishStatus ? "✏️" : "⬆️",
        class: "card-btn card-btn-primary",
        action: () => this.performAction(post, post.publishStatus ? "update" : "publish"),
      },
      {
        text: "🔄",
        class: "card-btn",
        action: () => this.performAction(post, "pull"),
      },
    ];

    for (const btn of actionButtons) {
      const button = cardActions.createEl("button", { text: btn.text, cls: btn.class });
      button.style.cssText = `
        width: 32px; height: 32px; border: 1px solid var(--border-color);
        border-radius: 6px; background: var(--background-primary);
        cursor: pointer; font-size: 14px; display: flex;
        align-items: center; justify-content: center;
        transition: all 0.2s;
      `;
      button.addEventListener("mouseenter", () => {
        button.style.background = "var(--interactive-accent)";
        button.style.borderColor = "var(--interactive-accent)";
      });
      button.addEventListener("mouseleave", () => {
        button.style.background = "var(--background-primary)";
        button.style.borderColor = "var(--border-color)";
      });
      button.addEventListener("click", btn.action);
    }
  }

  private showHistory() {
    const modal = document.createElement("div");
    modal.className = "sync-history-modal";
    modal.style.cssText = `
      position: fixed; top: 0; left: 0; right: 0; bottom: 0;
      background: rgba(0,0,0,0.5); display: flex; align-items: center;
      justify-content: center; z-index: 1000;
    `;

    const content = document.createElement("div");
    content.className = "sync-history-content";
    content.style.cssText = `
      background: var(--background-primary); padding: 24px;
      border-radius: 12px; width: 520px; max-height: 80vh;
      overflow-y: auto; box-shadow: 0 8px 32px rgba(0,0,0,0.3);
    `;

    const title = content.createElement("h3");
    title.textContent = i18next.t("sync_history.title");
    title.style.cssText = "margin: 0 0 16px 0;";

    if (this.history.length > 0) {
      const stats = document.createElement("div");
      stats.style.cssText = "font-size: 12px; color: var(--text-muted); margin-bottom: 16px;";
      const successCount = this.history.filter((h) => h.success).length;
      stats.textContent = i18next.t("sync_history.stats", { total: this.history.length, success: successCount });
      content.appendChild(stats);
    }

    const closeBtn = content.createElement("button");
    closeBtn.textContent = i18next.t("common.button_close");
    closeBtn.style.cssText = "margin-bottom: 16px;";
    closeBtn.addEventListener("click", () => modal.remove());

    if (this.history.length === 0) {
      const empty = content.createElement("p");
      empty.textContent = i18next.t("sync_history.empty");
      empty.className = "history-empty";
    } else {
      const list = content.createElement("div");
      list.className = "sync-history-list";

      for (const item of [...this.history].reverse()) {
        const historyItem = document.createElement("div");
        historyItem.style.cssText = `
          display: flex; justify-content: space-between; align-items: center;
          padding: 10px; border-bottom: 1px solid var(--border-color);
        `;

        const info = document.createElement("div");
        info.style.cssText = "display: flex; align-items: center; gap: 8px;";
        info.innerHTML = `<span>${item.success ? "✅" : "❌"}</span><span>${i18next.t(`sync_history.action_${item.action}`)}: ${item.title}</span>`;

        const time = document.createElement("span");
        time.style.cssText = "font-size: 11px; color: var(--text-muted);";
        time.textContent = new Date(item.timestamp).toLocaleString();

        historyItem.appendChild(info);
        historyItem.appendChild(time);
        list.appendChild(historyItem);
      }
      content.appendChild(list);
    }

    const clearBtn = content.createElement("button");
    clearBtn.textContent = i18next.t("sync_panel.button_clear_history");
    clearBtn.className = "history-clear-btn";
    clearBtn.style.cssText = "width: 100%; margin-top: 16px;";
    clearBtn.addEventListener("click", () => {
      this.clearHistory();
      modal.remove();
    });

    modal.addEventListener("click", (e) => {
      if (e.target === modal) modal.remove();
    });

    content.insertBefore(closeBtn, content.firstChild);
    content.appendChild(clearBtn);
    modal.appendChild(content);
    document.body.appendChild(modal);
  }

  private clearHistory() {
    if (confirm(i18next.t("sync_history.confirm_clear"))) {
      this.history = [];
      this.saveHistory();
      this.render();
      new Notice(i18next.t("sync_history.notice_cleared"));
    }
  }
}