import { AxiosError } from 'axios';
import type { RequestHandler } from 'express';
import { FinanceApiClient } from '../services/api/FinanceApiClient';
import { AppError } from '../utils/AppError';

const financeApi = new FinanceApiClient();

interface LoginResponse {
  id: string | number;
  nome: string;
  email: string;
}

function parseBasicAuth(authorization?: string): { username: string; password: string } | null {
  if (!authorization?.startsWith('Basic ')) {
    return null;
  }

  const decoded = Buffer.from(authorization.slice(6), 'base64').toString('utf8');
  const separatorIndex = decoded.indexOf(':');

  if (separatorIndex <= 0) {
    return null;
  }

  return {
    username: decoded.slice(0, separatorIndex),
    password: decoded.slice(separatorIndex + 1),
  };
}

export const authMiddleware: RequestHandler = async (req, _res, next) => {
  const authorization = req.header('authorization');
  const credentials = parseBasicAuth(authorization);

  if (!credentials) {
    next(new AppError('Finance user Basic Auth credentials are required.', 401, 'AGENT_USER_AUTH_REQUIRED'));
    return;
  }

  try {
    const user = await financeApi.post<LoginResponse>('/login', {
      email: credentials.username,
      senha: credentials.password,
    });
    const userId = Number(user.id);

    if (!Number.isInteger(userId) || userId <= 0) {
      next(new AppError('Finance API returned an invalid user identity.', 502, 'INVALID_FINANCE_USER'));
      return;
    }

    req.authContext = {
      user: {
        id: userId,
        nome: user.nome,
        email: user.email,
      },
      basicAuth: credentials,
    };

    next();
  } catch (error) {
    if (error instanceof AxiosError && error.response?.status === 401) {
      next(new AppError('Invalid finance user credentials.', 401, 'AGENT_USER_AUTH_INVALID'));
      return;
    }

    next(error);
  }
};
