// @ts-nocheck
import express from "express";
import fs from "fs";
import path from "path";
import { ShopifyRenderer, RendererOptions } from "./renderer.js";
import { ShopifyCredentials } from "./theme-manager.js";
import { createLogger } from "../logger.js";
import Shopify from "shopify-api-node";
import { ThemeManager } from "./theme-manager.js";
import { ThemeAPI } from "./theme-api.js";
import { ThemeChecker, ThemeCheckResult } from "./theme-checker.js";
import {
  devUIHtml,
  devUIStyles,
  errorPageTemplate,
  devUIScript,
} from "./templates/index.js";

const logger = createLogger("dev-server");

interface DevServerOptions {
  port: number;
  themeDir: string;
  shopify: Shopify;
  themeManager: ThemeManager;
  credentials: {
    storeName: string;
    apiKey: string;
    password: string;
  };
  themeId: number;
  debug?: boolean;
}

/**
 * A simple development server for Shopify themes
 * Provides a UI for browsing theme files and previewing them
 */
export class SimpleDevServer {
  private app: express.Application;
  private renderer: ShopifyRenderer;
  private themeDir: string;
  private port: number;
  private server: ReturnType<typeof this.app.listen> | null = null;
  private themeAPI: ThemeAPI;
  private themeManager: ThemeManager;
  private credentials: DevServerOptions["credentials"];
  private themeId: number;
  private themeChecker: ThemeChecker;
  private devUIHtml: string;
  private devUIStyles: string;
  private errorPageTemplate: string;
  private debug: boolean;

  constructor(options: DevServerOptions) {
    this.app = express();
    this.debug = options.debug || false;
    this.renderer = new ShopifyRenderer({
      credentials: options.credentials,
      themeId: options.themeId,
      shopify: options.shopify,
      debug: this.debug,
    });
    this.themeDir = options.themeDir;
    this.port = options.port || 3000;
    this.themeManager = options.themeManager;
    this.credentials = options.credentials;
    this.themeId = options.themeId;
    this.themeAPI = new ThemeAPI(
      options.shopify,
      this.themeManager,
      this.themeDir
    );
    this.themeChecker = new ThemeChecker(this.themeDir);

    // Load templates
    this.devUIHtml = devUIHtml;
    this.devUIStyles = devUIStyles;
    this.errorPageTemplate = errorPageTemplate;

    this.configureMiddleware();
    this.configureRoutes();
    this.configureErrorHandling();

    if (this.debug) {
      logger.info("Debug mode enabled");
      logger.info(`Theme directory: ${this.themeDir}`);
      logger.info(`Theme ID: ${this.themeId}`);
      logger.info(`Store: ${this.credentials.storeName}`);
    }
  }

  private configureMiddleware(): void {
    this.app.use(express.json());
    this.app.use(express.static("public"));

    if (this.debug) {
      // Add request logging middleware
      this.app.use((req, res, next) => {
        logger.info(`${req.method} ${req.path}`);
        next();
      });
    }
  }

  private configureRoutes(): void {
    this.app.get("/dev-ui.css", (req, res) => {
      res.type("text/css").send(devUIStyles);
    });

    this.app.get("/dev-ui.js", (req, res) => {
      res.type("application/javascript").send(devUIScript);
    });

    this.app.get("/api/theme/metadata", async (req, res) => {
      try {
        const metadata = await this.renderer.getThemeMetadata();
        res.json(metadata);
      } catch (err) {
        const error = err as Error;
        this.logError("Failed to get theme metadata", error);
        res.status(500).json({ error: error.message });
      }
    });

    this.app.get("/api/theme/pages", async (req, res) => {
      try {
        const pages = await this.renderer.getThemePages();
        res.json(pages);
      } catch (err) {
        const error = err as Error;
        this.logError("Failed to get theme pages", error);
        res.status(500).json({ error: error.message });
      }
    });

    this.app.get("/api/theme/page/:path(*)", async (req, res) => {
      try {
        if (this.debug) {
          logger.info(`Getting page metadata for path: ${req.params.path}`);
        }

        const page = await this.renderer.getPageMetadata(req.params.path);

        if (!page) {
          if (this.debug) {
            logger.warn(`No page metadata found for path: ${req.params.path}`);
          }
          res.status(404).json({ error: "Page not found" });
          return;
        }

        const templatePath = path.join(
          this.renderer.themePath,
          "templates",
          page.template + ".json"
        );

        if (this.debug) {
          logger.info(`Looking for template at: ${templatePath}`);
        }

        if (!this.renderer.fileExists(templatePath)) {
          const error = new Error(`Template file not found: ${templatePath}`);
          throw error;
        }

        const templateContent = await this.renderer.renderTemplate(
          templatePath
        );
        res.json({ ...page, content: templateContent });
      } catch (err) {
        const error = err as Error;
        this.logError(
          `Failed to get page metadata for ${req.params.path}`,
          error
        );
        res.status(500).json({ error: error.message });
      }
    });

    this.app.get("*", async (req, res) => {
      try {
        const page = await this.renderer.getPageMetadata(req.path);
        const attributes = page?.attributes ? " " + page.attributes : "";
        const currentPage = encodeURIComponent(req.path);

        const html = devUIHtml.replace(
          "<body>",
          `<body${attributes} data-current-page="${currentPage}">`
        );

        res.send(html);
      } catch (error) {
        this.handleError(error as Error, req, res);
      }
    });
  }

  private configureErrorHandling(): void {
    this.app.use((err: Error, req: express.Request, res: express.Response) => {
      this.handleError(err, req, res);
    });
  }

  private logError(message: string, error: Error): void {
    logger.error(`${message}: ${error.message}`);
    if (this.debug && error.stack) {
      logger.error("Stack trace:");
      logger.error(error.stack);
    }
  }

  private handleError(
    error: Error,
    req: express.Request,
    res: express.Response
  ): void {
    this.logError("Server error", error);

    const errorPage = errorPageTemplate
      .replace("{{message}}", error.message)
      .replace("{{stack}}", this.debug ? error.stack || "" : "");

    res.status(500).send(errorPage);
  }

  /**
   * Starts the development server
   * @returns Promise that resolves with the server URL
   */
  start(): Promise<string> {
    return new Promise((resolve) => {
      this.server = this.app.listen(this.port, () => {
        const serverUrl = `http://localhost:${this.port}`;
        logger.success(`Development server running at ${serverUrl}`);
        if (this.debug) {
          logger.info("Debug mode enabled - verbose logging is active");
        }
        console.log(`API endpoints:`);
        console.log(`  - GET /api/theme/metadata`);
        console.log(`  - GET /api/theme/pages`);
        console.log(`  - GET /api/theme/page/:path`);
        resolve(serverUrl);
      });
    });
  }

  /**
   * Stops the development server
   */
  stop(): void {
    if (this.server) {
      this.server.close();
      logger.info("Development server stopped");
    }
  }
}
