import type { NextFunction, Request, Response } from 'express';
import type { IncomingHttpHeaders } from 'http';
import { UserAgent } from './express-useragent';
import type { AgentDetails } from './express-useragent';

export type { AgentDetails, HeadersLike, ClientHints, ClientHintBrand } from './express-useragent';
export { UserAgent } from './express-useragent';

// Declaration merging for Express Request
// This allows TypeScript users to access req.useragent without type errors
declare global {
  // eslint-disable-next-line @typescript-eslint/no-namespace
  namespace Express {
    interface Request {
      useragent?: AgentDetails;
    }
  }
}

export interface UserAgentAugmentedRequest extends Request {
  useragent?: ReturnType<UserAgent['parse']>;
  headers: IncomingHttpHeaders & Record<string, string | string[] | undefined>;
}

export const useragent = new UserAgent();

export type UserAgentMiddleware = (req: Request, res: Response, next: NextFunction) => void;

export const express = (): UserAgentMiddleware => {
  return (req: UserAgentAugmentedRequest, res: Response, next: NextFunction) => {
    const headers = req.headers || {};
    const resolveHeader = (value: string | string[] | undefined): string => {
      if (Array.isArray(value)) {
        return value.join(' ');
      }
      return value ?? '';
    };

    const uaHeader = resolveHeader(headers['user-agent']);
    const ucHeader = resolveHeader(headers['x-ucbrowser-ua']);
    const source = (ucHeader || uaHeader || 'unknown').trim() || 'unknown';

    const parser = new UserAgent().hydrateFromHeaders(source, headers);
    parser.testNginxGeoIP(headers);
    // middleware duplicates tests to match legacy behaviour
    parser.testBot();
    parser.testMobile();
    parser.testAndroidTablet();
    parser.testTablet();
    parser.testCompatibilityMode();
    parser.testSilk();
    parser.testKindleFire();
    parser.testWechat();

    req.useragent = parser.Agent;
    res.locals.useragent = parser.Agent;

    next();
  };
};
export const useragentMiddleware = express;

// Export a default instance for easier usage
// Also attach the express middleware and UserAgent class to the default export
// to maintain compatibility with documented ESM usage (issue #177)
const defaultExport = Object.assign(useragent, {
  express,
  UserAgent,
});

export default defaultExport;
