import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { generateChuanglanSign } from './sign';
import { loadChuanglanConfig } from './config';
import type { ChuanglanSendResponse, SmsSendResult } from '../sms.types';
import { maskPhoneForLog, shortSessionId } from '../sms-log.util';

@Injectable()
export class ChuanglanClient {
  private readonly logger = new Logger(ChuanglanClient.name);
  private readonly cfg: ReturnType<typeof loadChuanglanConfig>;

  constructor(config: ConfigService) {
    this.cfg = loadChuanglanConfig(config);
    if (!this.cfg) {
      this.logger.warn(
        'Chuanglan SMS not configured (missing CHUANGLAN_ACCOUNT or CHUANGLAN_PASSWORD); SMS send will fail until credentials are set',
      );
    }
  }

  async sendSms(mobile: string, msg: string, uid?: string): Promise<SmsSendResult> {
    const maskedMobile = maskPhoneForLog(mobile);
    const session = uid ? shortSessionId(uid) : 'n/a';

    if (!this.cfg) {
      this.logger.error(
        `Chuanglan not configured mobile=${maskedMobile} session=${session}`,
      );
      return {
        success: false,
        code: 'NOT_CONFIGURED',
        message: 'Missing CHUANGLAN_ACCOUNT or CHUANGLAN_PASSWORD',
      };
    }

    const nonce = String(Date.now());

    this.logger.log(`Chuanglan request mobile=${maskedMobile} session=${session}`);

    const body: Record<string, string> = {
      account: this.cfg.account,
      mobile,
      msg,
    };
    if (uid) body.uid = uid;

    const sign = generateChuanglanSign(this.cfg.password, { ...body, nonce });

    const controller = new AbortController();
    const timer = setTimeout(() => controller.abort(), this.cfg.readTimeoutMs);

    try {
      const res = await fetch(this.cfg.endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          nonce,
          sign,
        },
        body: JSON.stringify(body),
        signal: controller.signal,
      });

      const data = (await res.json()) as ChuanglanSendResponse;

      if (data.code === '0') {
        this.logger.log(
          `Chuanglan success mobile=${maskedMobile} session=${session} messageId=${data.data?.messageId ?? 'n/a'}`,
        );
        return {
          success: true,
          code: data.code,
          message: 'OK',
          messageId: data.data?.messageId,
        };
      }

      this.logger.warn(
        `Chuanglan rejected mobile=${maskedMobile} session=${session} code=${data.code} message=${data.message ?? 'n/a'}`,
      );
      return { success: false, code: data.code, message: data.message };
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Unknown error';
      this.logger.error(
        `Chuanglan HTTP error mobile=${maskedMobile} session=${session} error=${message}`,
      );
      return { success: false, code: 'HTTP_ERROR', message };
    } finally {
      clearTimeout(timer);
    }
  }
}
