import i18next from "i18next";
import { Notice, Plugin, moment } from "obsidian";
import { resources } from "./i18n";
import { addHaloIcon } from "./icons";
import { openPostSelectionModal } from "./post-selection-model";
import { importFromMarkdownFile } from "./commands/import-markdown";
import { deletePost } from "./commands/delete-post";
import { manageTags, manageCategories } from "./commands/manage-taxonomy";
import { exportPostAsMarkdown, exportPostAsJson } from "./commands/export-post";
import { searchPosts } from "./commands/search-posts";
import { SyncStatusView, SYNC_STATUS_VIEW_TYPE } from "./views/sync-status-view";
import { DEFAULT_SETTINGS, type HaloSetting, HaloSettingTab, type HaloSite } from "./settings";
import HaloService from "./service";
import { openSiteSelectionModal } from "./site-selection-modal";

export default class HaloPlugin extends Plugin {
  settings: HaloSetting;

  async onload() {
    console.log("loading obsidian-halo plugin");

    await i18next.init({
      lng: moment.locale(),
      fallbackLng: "en",
      resources,
      returnNull: false,
    });

    await this.loadSettings();

    addHaloIcon();

    this.addRibbonIcon("halo-logo", i18next.t("ribbon_icon.publish"), async (evt: MouseEvent) => {
      await this.publishCommand();
    });

    this.addRibbonIcon("sync-icon", i18next.t("ribbon_icon.sync_status"), async (evt: MouseEvent) => {
      await this.openSyncStatusPanel();
    });

    this.addCommand({
      id: "publish",
      name: i18next.t("command.publish.name"),
      callback: async () => {
        await this.publishCommand();
      },
    });

    this.addCommand({
      id: "publish-with-defaults",
      name: i18next.t("command.publish_with_defaults.name"),
      callback: async () => {
        const site = this.settings.sites.find((site) => site.default);

        if (!site) {
          new Notice(i18next.t("command.publish_with_defaults.error_no_default_site"));
          return;
        }

        const service = new HaloService(this.app, this.settings, site);
        await service.publishPost();
      },
    });

    this.addCommand({
      id: "update-post",
      name: i18next.t("command.update_post.name"),
      editorCallback: async () => {
        const { activeEditor } = this.app.workspace;

        if (!activeEditor || !activeEditor.file) {
          return;
        }

        const matterData = this.app.metadataCache.getFileCache(activeEditor.file)?.frontmatter;

        if (!matterData?.halo?.site) {
          new Notice(i18next.t("command.update_post.error_not_published"));
          return;
        }

        const site = this.settings.sites.find((site) => site.url === matterData.halo?.site);

        if (!site) {
          new Notice(i18next.t("command.update_post.error_no_matched_site"));
          return;
        }

        const service = new HaloService(this.app, this.settings, site);

        await service.updatePost();

        new Notice(i18next.t("command.update_post.success"));
      },
    });

    this.addCommand({
      id: "pull-post",
      name: i18next.t("command.pull_post.name"),
      callback: async () => {
        if (this.settings.sites.length === 0) {
          new Notice(i18next.t("command.pull_post.error_no_sites"));
          return;
        }

        let site: HaloSite = this.settings.sites[0];

        if (this.settings.sites.length > 1) {
          site = await openSiteSelectionModal(this);
        }

        const post = await openPostSelectionModal(this, site);

        const service = new HaloService(this.app, this.settings, site);
        await service.pullPost(post.post.metadata.name);
      },
    });

    this.addCommand({
      id: "import-markdown",
      name: i18next.t("command.import_markdown.name"),
      callback: async () => {
        await importFromMarkdownFile(this);
      },
    });

    this.addCommand({
      id: "delete-post",
      name: i18next.t("command.delete_post.name"),
      editorCallback: async () => {
        await deletePost(this);
      },
    });

    this.addCommand({
      id: "manage-tags",
      name: i18next.t("command.manage_tags.name"),
      callback: async () => {
        await manageTags(this);
      },
    });

    this.addCommand({
      id: "manage-categories",
      name: i18next.t("command.manage_categories.name"),
      callback: async () => {
        await manageCategories(this);
      },
    });

    this.addCommand({
      id: "search-posts",
      name: i18next.t("command.search_posts.name"),
      callback: async () => {
        await searchPosts(this);
      },
    });

    this.addCommand({
      id: "export-post-as-markdown",
      name: i18next.t("command.export_markdown.name"),
      editorCallback: async () => {
        const { activeEditor } = this.app.workspace;
        if (!activeEditor || !activeEditor.file) return;
        const matterData = this.app.metadataCache.getFileCache(activeEditor.file)?.frontmatter;
        if (!matterData?.halo?.name) {
          new Notice(i18next.t("command.export_markdown.error_not_published"));
          return;
        }
        await exportPostAsMarkdown(this, matterData.halo.name, matterData.title || activeEditor.file.basename);
      },
    });

    this.addCommand({
      id: "export-post-as-json",
      name: i18next.t("command.export_json.name"),
      editorCallback: async () => {
        const { activeEditor } = this.app.workspace;
        if (!activeEditor || !activeEditor.file) return;
        const matterData = this.app.metadataCache.getFileCache(activeEditor.file)?.frontmatter;
        if (!matterData?.halo?.name) {
          new Notice(i18next.t("command.export_json.error_not_published"));
          return;
        }
        await exportPostAsJson(this, matterData.halo.name, matterData.title || activeEditor.file.basename);
      },
    });

    this.addCommand({
      id: "open-sync-status-panel",
      name: i18next.t("command.open_sync_panel.name"),
      callback: async () => {
        await this.openSyncStatusPanel();
      },
    });

    this.addSettingTab(new HaloSettingTab(this));

    this.registerView(SYNC_STATUS_VIEW_TYPE, (leaf) => new SyncStatusView(leaf, this));
  }

  async openSyncStatusPanel() {
    const leaf = this.app.workspace.getRightLeaf(false);
    if (leaf) {
      await leaf.setViewState({ type: SYNC_STATUS_VIEW_TYPE });
    }
  }

  onunload() {}

  async loadSettings() {
    this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
  }

  async saveSettings() {
    await this.saveData(this.settings);
  }

  private async publishCommand() {
    console.log("[HaloPlugin] 执行发布命令");
    
    const { activeEditor } = this.app.workspace;
    console.log(`[HaloPlugin] activeEditor: ${activeEditor ? '存在' : '不存在'}`);

    if (!activeEditor || !activeEditor.file) {
      console.log("[HaloPlugin] 没有打开的编辑器，退出");
      return;
    }

    console.log(`[HaloPlugin] 当前文件: ${activeEditor.file.path}`);

    const matterData = this.app.metadataCache.getFileCache(activeEditor.file)?.frontmatter;
    console.log(`[HaloPlugin] frontmatter: ${JSON.stringify(matterData)}`);

    if (matterData?.halo?.site) {
      console.log(`[HaloPlugin] 检测到已发布的文章，站点: ${matterData.halo.site}`);
      const site = this.settings.sites.find((site) => site.url === matterData.halo.site);

      if (!site) {
        console.log("[HaloPlugin] 未找到匹配的站点配置");
        new Notice(i18next.t("command.publish.error_no_matched_site"));
        return;
      }

      console.log(`[HaloPlugin] 找到站点: ${site.name}, URL: ${site.url}`);
      const service = new HaloService(this.app, this.settings, site);
      await service.publishPost();
      return;
    }

    console.log("[HaloPlugin] 文章未发布过，需要选择站点");
    const site = await openSiteSelectionModal(this);
    console.log(`[HaloPlugin] 选择站点: ${site.name}, URL: ${site.url}`);
    const service = new HaloService(this.app, this.settings, site);
    await service.publishPost();
  }
}
