import * as plugins from '../plugins.js';
import * as paths from '../paths.js';

/**
 * Built-in routes controller for TypedServer
 * Handles robots.txt, manifest.json, sitemap, feed, appversion
 */
@plugins.smartserve.Route('')
export class BuiltInRoutesController {
  private options: {
    domain?: string;
    robots?: boolean;
    manifest?: plugins.smartmanifest.SmartManifest;
    sitemap?: boolean;
    feed?: boolean;
    appVersion?: string;
    feedMetadata?: plugins.smartfeed.IFeedOptions;
    articleGetterFunction?: () => Promise<plugins.tsclass.content.IArticle[]>;
    blockWaybackMachine?: boolean;
    getSitemapUrls: () => plugins.smartsitemap.ISitemapUrl[];
  };

  constructor(options: typeof BuiltInRoutesController.prototype.options) {
    this.options = options;
  }

  @plugins.smartserve.Get('/robots.txt')
  async getRobots(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
    if (!this.options.robots || !this.options.domain) {
      throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
    }

    const robotsContent = [
      'User-agent: *',
      'Allow: /',
      `Sitemap: https://${this.options.domain}/sitemap`,
    ];

    if (this.options.blockWaybackMachine) {
      robotsContent.push('', 'User-agent: ia_archiver', 'Disallow: /');
    }

    return new Response(robotsContent.join('\n'), {
      status: 200,
      headers: { 'Content-Type': 'text/plain' },
    });
  }

  @plugins.smartserve.Get('/manifest.json')
  async getManifest(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
    if (!this.options.manifest) {
      throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
    }

    return new Response(this.options.manifest.jsonString(), {
      status: 200,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  @plugins.smartserve.Get('/sitemap')
  async getSitemap(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
    if (!this.options.sitemap || !this.options.domain) {
      throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
    }

    const urls = this.options.getSitemapUrls();
    const sitemapXml = plugins.smartsitemap.SmartSitemap.create().addUrls(urls).toXml();

    return new Response(sitemapXml, {
      status: 200,
      headers: { 'Content-Type': 'application/xml' },
    });
  }

  @plugins.smartserve.Get('/sitemap-news')
  async getSitemapNews(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
    if (!this.options.sitemap || !this.options.domain || !this.options.articleGetterFunction) {
      throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
    }

    const articles = await this.options.articleGetterFunction();
    const sitemapNewsXml = plugins.smartsitemap.SmartSitemap.fromArticles(articles, { publicationName: this.options.domain || 'News' }).toXml();

    return new Response(sitemapNewsXml, {
      status: 200,
      headers: { 'Content-Type': 'application/xml' },
    });
  }

  @plugins.smartserve.Get('/feed')
  async getFeed(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
    if (!this.options.feed || !this.options.feedMetadata) {
      throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
    }

    const smartfeed = new plugins.smartfeed.Smartfeed();
    const articles = this.options.articleGetterFunction
      ? await this.options.articleGetterFunction()
      : [];

    const feedXml = await smartfeed.createFeedFromArticleArray(
      this.options.feedMetadata,
      articles
    );

    return new Response(feedXml, {
      status: 200,
      headers: { 'Content-Type': 'application/atom+xml' },
    });
  }

  @plugins.smartserve.Get('/appversion')
  async getAppVersion(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
    if (!this.options.appVersion) {
      throw new plugins.smartserve.RouteNotFoundError(ctx.path, ctx.method);
    }

    return new Response(this.options.appVersion, {
      status: 200,
      headers: { 'Content-Type': 'text/plain' },
    });
  }

  @plugins.smartserve.Get('/sw-dash')
  async getSwDash(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
    // Import shared HTML from interfaces
    const { SW_DASH_HTML } = await import('../../ts_interfaces/serviceworker.js');
    return new Response(SW_DASH_HTML, {
      status: 200,
      headers: { 'Content-Type': 'text/html' },
    });
  }

  // SW-dash data routes - return empty/unavailable when SW isn't active
  @plugins.smartserve.Get('/sw-dash/metrics')
  async getSwDashMetrics(): Promise<Response> {
    return new Response(JSON.stringify({ error: 'Service worker not active', data: null }), {
      status: 503,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  @plugins.smartserve.Get('/sw-dash/resources')
  async getSwDashResources(): Promise<Response> {
    return new Response(JSON.stringify({ error: 'Service worker not active', resources: [], domains: [], contentTypes: [], resourceCount: 0 }), {
      status: 503,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  @plugins.smartserve.Get('/sw-dash/events')
  async getSwDashEvents(): Promise<Response> {
    return new Response(JSON.stringify({ error: 'Service worker not active', events: [], total: 0 }), {
      status: 503,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  @plugins.smartserve.Get('/sw-dash/events/count')
  async getSwDashEventsCount(): Promise<Response> {
    return new Response(JSON.stringify({ error: 'Service worker not active', count: 0 }), {
      status: 503,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  @plugins.smartserve.Get('/sw-dash/cumulative-metrics')
  async getSwDashCumulativeMetrics(): Promise<Response> {
    return new Response(JSON.stringify({ error: 'Service worker not active', data: null }), {
      status: 503,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  @plugins.smartserve.Get('/sw-dash/speedtest')
  async getSwDashSpeedtest(): Promise<Response> {
    return new Response(JSON.stringify({ error: 'Service worker not active - speedtest unavailable' }), {
      status: 503,
      headers: { 'Content-Type': 'application/json' },
    });
  }

  @plugins.smartserve.Get('/sw-dash/bundle.js')
  async getSwDashBundle(ctx: plugins.smartserve.IRequestContext): Promise<Response> {
    try {
      const bundleContent = (await plugins.fsInstance
        .file(paths.swdashBundlePath)
        .encoding('utf8')
        .read()) as string;

      return new Response(bundleContent, {
        status: 200,
        headers: {
          'Content-Type': 'text/javascript',
          'Cache-Control': 'no-cache',
        },
      });
    } catch (error) {
      console.error('Failed to serve sw-dash bundle:', error);
      return new Response('SW-Dash bundle not found', { status: 404 });
    }
  }

  @plugins.smartserve.Get('/serviceworker.bundle.js')
  async getServiceWorkerBundle(): Promise<Response> {
    try {
      const bundleContent = (await plugins.fsInstance
        .file(paths.serviceworkerBundlePath)
        .encoding('utf8')
        .read()) as string;

      return new Response(bundleContent, {
        status: 200,
        headers: {
          'Content-Type': 'text/javascript',
          'Cache-Control': 'no-cache',
        },
      });
    } catch (error) {
      console.error('Failed to serve serviceworker bundle:', error);
      return new Response('ServiceWorker bundle not found', { status: 404 });
    }
  }
}
