import { WordPressClient } from "@/client/api.js";
import type { MCPToolSchema } from "@/types/mcp.js";
import { WordPressApplicationPassword } from "@/types/wordpress.js";
import { getErrorMessage } from "@/utils/error.js";

/**
 * Provides tools for managing general site settings and operations on a WordPress site.
 * This class encapsulates tool definitions and their corresponding handlers.
 */
export class SiteTools {
  /**
   * Retrieves the list of site management tools.
   * @returns An array of MCPTool definitions.
   */
  public getTools(): Array<{
    name: string;
    description: string;
    inputSchema?: MCPToolSchema;
    handler: (client: WordPressClient, params: Record<string, unknown>) => Promise<unknown>;
  }> {
    return [
      {
        name: "wp_get_site_settings",
        description:
          "Retrieves the general settings for a WordPress site. Requires administrator role (manage_options capability).",
        inputSchema: {
          type: "object",
          properties: {},
        },
        handler: this.handleGetSiteSettings.bind(this),
      },
      {
        name: "wp_update_site_settings",
        description:
          "Updates one or more general settings for a WordPress site. Requires administrator role (manage_options capability).",
        inputSchema: {
          type: "object",
          properties: {
            title: {
              type: "string",
              description: "The title of the site.",
            },
            description: {
              type: "string",
              description: "The tagline or description of the site.",
            },
            timezone: {
              type: "string",
              description: "A city in the same timezone, e.g., 'America/New_York'.",
            },
          },
        },
        handler: this.handleUpdateSiteSettings.bind(this),
      },
      {
        name: "wp_search_site",
        description:
          "Performs a site-wide search for content across posts, pages, and media with comprehensive results and metadata.\n\n" +
          "**Usage Examples:**\n" +
          '• Search everything: `wp_search_site --term="WordPress"`\n' +
          '• Search posts only: `wp_search_site --term="tutorial" --type="posts"`\n' +
          '• Search pages: `wp_search_site --term="about" --type="pages"`\n' +
          '• Search media: `wp_search_site --term="logo" --type="media"`\n' +
          '• Find specific content: `wp_search_site --term="contact form"`',
        inputSchema: {
          type: "object",
          properties: {
            term: {
              type: "string",
              description: "The search term to look for.",
            },
            type: {
              type: "string",
              description: "The type of content to search.",
              enum: ["posts", "pages", "media"],
            },
          },
          required: ["term"],
        },
        handler: this.handleSearchSite.bind(this),
      },
      {
        name: "wp_get_application_passwords",
        description: "Lists application passwords for a specific user.",
        inputSchema: {
          type: "object",
          properties: {
            user_id: {
              type: "number",
              description: "The ID of the user to get application passwords for.",
            },
          },
          required: ["user_id"],
        },
        handler: this.handleGetApplicationPasswords.bind(this),
      },
      {
        name: "wp_create_application_password",
        description: "Creates a new application password for a user.",
        inputSchema: {
          type: "object",
          properties: {
            user_id: {
              type: "number",
              description: "The ID of the user to create the password for.",
            },
            app_name: {
              type: "string",
              description: "The name of the application this password is for.",
            },
          },
          required: ["user_id", "app_name"],
        },
        handler: this.handleCreateApplicationPassword.bind(this),
      },
      {
        name: "wp_delete_application_password",
        description: "Revokes an existing application password.",
        inputSchema: {
          type: "object",
          properties: {
            user_id: {
              type: "number",
              description: "The ID of the user who owns the password.",
            },
            uuid: {
              type: "string",
              description: "The UUID of the application password to revoke.",
            },
          },
          required: ["user_id", "uuid"],
        },
        handler: this.handleDeleteApplicationPassword.bind(this),
      },
    ];
  }

  public async handleGetSiteSettings(client: WordPressClient, _params: Record<string, unknown>): Promise<unknown> {
    try {
      const settings = await client.getSiteSettings();
      const siteUrl = client.getSiteUrl();

      // Enhanced site settings with comprehensive details
      const weekDays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
      const startOfWeek = settings.start_of_week !== undefined ? weekDays[settings.start_of_week] : "Not set";

      // Get additional site information
      const currentTime = new Date().toLocaleString("en-US", {
        timeZone: settings.timezone || "UTC",
        weekday: "long",
        year: "numeric",
        month: "long",
        day: "numeric",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
        timeZoneName: "short",
      });

      let content = `**🌐 Site Settings for ${siteUrl}**\n\n`;

      content += `**📋 Basic Information:**\n`;
      content += `- **Title:** ${settings.title || "Not set"}\n`;
      content += `- **Description:** ${settings.description || "Not set"}\n`;
      content += `- **URL:** ${settings.url || siteUrl}\n`;
      content += `- **Admin Email:** ${settings.email || "Not set"}\n\n`;

      content += `**🌍 Localization:**\n`;
      content += `- **Language:** ${settings.language || "English (US)"}\n`;
      content += `- **Timezone:** ${settings.timezone || "UTC"}\n`;
      content += `- **Current Time:** ${currentTime}\n\n`;

      content += `**📅 Date & Time Format:**\n`;
      content += `- **Date Format:** ${settings.date_format || "Not set"}\n`;
      content += `- **Time Format:** ${settings.time_format || "Not set"}\n`;
      content += `- **Start of Week:** ${startOfWeek}\n\n`;

      content += `**📝 Content Settings:**\n`;
      content += `- **Posts per Page:** ${settings.posts_per_page || "Not set"}\n`;
      content += `- **Default Category:** ${settings.default_category || "Not set"}\n`;
      content += `- **Default Post Format:** ${settings.default_post_format || "Standard"}\n\n`;

      content += `**💬 Discussion Settings:**\n`;
      content += `- **Default Comment Status:** ${settings.default_comment_status || "Not set"}\n`;
      content += `- **Default Ping Status:** ${settings.default_ping_status || "Not set"}\n`;
      content += `- **Use Smilies:** ${settings.use_smilies ? "Yes" : "No"}\n\n`;

      content += `**📊 Retrieved:** ${new Date().toLocaleString()}`;

      return content;
    } catch (_error) {
      throw new Error(`Failed to get site settings: ${getErrorMessage(_error)}`);
    }
  }

  public async handleUpdateSiteSettings(client: WordPressClient, params: Record<string, unknown>): Promise<unknown> {
    try {
      const updatedSettings = await client.updateSiteSettings(params);
      return `✅ Site settings updated successfully. New title: ${updatedSettings.title}`;
    } catch (_error) {
      throw new Error(`Failed to update site settings: ${getErrorMessage(_error)}`);
    }
  }

  public async handleSearchSite(client: WordPressClient, params: Record<string, unknown>): Promise<unknown> {
    try {
      const { term, type } = params as { term: string; type?: "posts" | "pages" | "media" };
      const results = await client.search(term, type ? [type] : undefined);
      if (results.length === 0) {
        return `No results found for "${term}".`;
      }
      const content =
        `Found ${results.length} results for "${term}":\n\n` +
        results.map((r) => `- [${r.type}] **${r.title}**\n  Link: ${r.url}`).join("\n");
      return content;
    } catch (_error) {
      throw new Error(`Failed to perform search: ${getErrorMessage(_error)}`);
    }
  }

  public async handleGetApplicationPasswords(
    client: WordPressClient,
    params: Record<string, unknown>,
  ): Promise<unknown> {
    try {
      const { user_id } = params as { user_id: number };
      const passwords = await client.getApplicationPasswords(user_id);
      if (passwords.length === 0) {
        return `No application passwords found for user ID ${user_id}.`;
      }
      const content =
        `Found ${passwords.length} application passwords for user ID ${user_id}:\n\n` +
        passwords
          .map(
            (p: WordPressApplicationPassword) =>
              `- **${p.name}** (UUID: ${p.uuid})\n  Created: ${new Date(p.created).toLocaleDateString()}`,
          )
          .join("\n");
      return content;
    } catch (_error) {
      throw new Error(`Failed to get application passwords: ${getErrorMessage(_error)}`);
    }
  }

  public async handleCreateApplicationPassword(
    client: WordPressClient,
    params: Record<string, unknown>,
  ): Promise<unknown> {
    try {
      const { user_id, app_name } = params as { user_id: number; app_name: string };
      const result = await client.createApplicationPassword(user_id, app_name);
      const content =
        "✅ **Application password created successfully!**\n\n" +
        `**Name:** ${result.name}\n` +
        `**Password:** \`${result.password}\`\n\n` +
        "**IMPORTANT:** This password is shown only once. Please save it securely.";
      return content;
    } catch (_error) {
      throw new Error(`Failed to create application password: ${getErrorMessage(_error)}`);
    }
  }

  public async handleDeleteApplicationPassword(
    client: WordPressClient,
    params: Record<string, unknown>,
  ): Promise<unknown> {
    try {
      const { user_id, uuid } = params as { user_id: number; uuid: string };
      await client.deleteApplicationPassword(user_id, uuid);
      return `✅ Application password with UUID ${uuid} has been revoked.`;
    } catch (_error) {
      throw new Error(`Failed to delete application password: ${getErrorMessage(_error)}`);
    }
  }
}

export default SiteTools;
