/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/naming-convention */
import {
  Count,
  CountSchema,
  Filter,
  FilterExcludingWhere,
  repository,
  Where,
} from '@loopback/repository';
import {
  del,
  get,
  getModelSchemaRef,
  param,
  patch,
  post,
  put,
  requestBody,
  response,
} from '@loopback/rest';
import {OtpVerification} from '../models';
import {BuyerMasterRepository, OtpVerificationRepository, SellerMasterRepository} from '../repositories';
import {sendOtpWhatsapp} from '../services/whatsapp.service';
export class OtpverificationController {
  constructor(
    @repository(OtpVerificationRepository)
    public otpVerificationRepository: OtpVerificationRepository,

    @repository(BuyerMasterRepository)
    public buyerRepository: BuyerMasterRepository,

    @repository(SellerMasterRepository)
    public sellerRepository: SellerMasterRepository,
  ) { }
  @post('/otp-verifications')
  async createOtp(
    @requestBody({
      content: {
        'application/json': {
          schema: {
            type: 'object',
            properties: {
              phone_number: {type: 'string'},
            },
            required: ['phone_number'],
          },
        },
      },
    })
    body: {phone_number: string},
  ): Promise<object> {
    const {phone_number} = body;

    const existingOtp = await this.otpVerificationRepository.findOne({
      where: {mobileNumber: phone_number},
      order: ['createdDate DESC'],
    });

    const now = new Date();

    if (existingOtp && existingOtp.expiresAt) {
      const expiresAt = new Date(existingOtp.expiresAt);

      if (!isNaN(expiresAt.getTime()) && now < expiresAt) {
        const remaining = Math.ceil((expiresAt.getTime() - now.getTime()) / 1000);

        return {
          success: true,
          message: `OTP already sent. Please wait ${remaining} seconds before requesting a new one.`,
          otp: existingOtp.otpCode, // ⚠️ only for console testing
        };
      }
    }

    // Generate new OTP
    const otp = Math.floor(1000 + Math.random() * 9000).toString();
    const expiresAt = new Date(now.getTime() + 2 * 60 * 1000); // 2 minutes

    await this.otpVerificationRepository.create({
      mobileNumber: phone_number,
      otpCode: otp,
      createdDate: now.toISOString(),
      expiresAt: expiresAt.toISOString(),
      lastChanged: now.toISOString(),
    });

    // ✅ Send WhatsApp OTP
    // const sent = await sendOtpWhatsapp(phone_number, otp);

    // if (!sent.success) {
    //   return {
    //     success: false,
    //     message: sent.error ?? 'Failed to send OTP via WhatsApp.',
    //     isWhatsapp: sent.isWhatsapp ?? false,
    //   };
    // }


    return {
      success: true,
      message: 'OTP sent successfully!',
      // message: 'OTP sent successfully via WhatsApp.',
      otp, // ⚠️ return for frontend console log
    };
  }


  // @post('/otp-verifications')
  // async createOtp(
  //   @requestBody({
  //     content: {
  //       'application/json': {
  //         schema: {
  //           type: 'object',
  //           properties: {
  //             phone_number: {type: 'string'},
  //           },
  //           required: ['phone_number'],
  //         },
  //       },
  //     },
  //   })
  //   body: {phone_number: string},
  // ): Promise<object> {
  //   const {phone_number} = body;

  //   const existingOtp = await this.otpVerificationRepository.findOne({
  //     where: {mobileNumber: phone_number},
  //     order: ['createdDate DESC'],
  //   });

  //   const now = new Date();

  //   if (existingOtp && existingOtp.expiresAt) {
  //     const expiresAt = new Date(existingOtp.expiresAt);

  //     if (!isNaN(expiresAt.getTime()) && now < expiresAt) {
  //       const remaining = Math.ceil((expiresAt.getTime() - now.getTime()) / 1000);

  //       return {
  //         success: true,
  //         message: `OTP already sent. Please wait ${remaining} seconds before requesting a new one.`,
  //         otp: existingOtp.otpCode, // For testing/debugging only
  //       };
  //     }
  //   }

  //   // Generate new OTP
  //   const otp = Math.floor(1000 + Math.random() * 9000).toString();
  //   const expiresAt = new Date(now.getTime() + 2 * 60 * 1000); // 2 minutes

  //   await this.otpVerificationRepository.create({
  //     mobileNumber: phone_number,
  //     otpCode: otp,
  //     createdDate: now.toISOString(),
  //     expiresAt: expiresAt.toISOString(),
  //     lastChanged: now.toISOString(),
  //   });

  //   Send WhatsApp OTP
  //   const sent = await sendOtpWhatsapp(phone_number, otp);

  //   if (!sent.success) {
  //     return {
  //       success: false,
  //       message: sent.error ? sent.error : 'Failed to send OTP via WhatsApp.',
  //       isWhatsapp: sent.isWhatsapp ?? false,
  //     };
  //   }

  //   return {
  //     success: true,
  //     message: 'OTP sent successfully!',
  //     // message: 'OTP sent successfully via WhatsApp.',
  //     otp, // For frontend console log
  //     // isWhatsapp: sent.isWhatsapp,
  //   };
  // }


  @post('/otp-verifications/verify')
  @response(200, {
    description: 'Verify OTP for given phone number',
    content: {'application/json': {schema: {type: 'object'}}},
  })
  async verifyOtp(
    @requestBody({
      content: {
        'application/json': {
          schema: {
            type: 'object',
            properties: {
              phone_number: {type: 'string'},
              otp: {type: 'string'},
            },
            required: ['phone_number', 'otp'],
          },
        },
      },
    })
    body: {phone_number: string; otp: string},
  ): Promise<object> {
    const {phone_number, otp} = body;

    const existing = await this.otpVerificationRepository.findOne({
      where: {
        mobileNumber: phone_number,
        otpCode: otp,
      },
      order: ['created_date DESC'],
    });

    if (!existing) {
      return {
        success: false,
        message: 'Invalid OTP or phone number.',
      };
    }

    // ✅ Safely check if `expires_at` exists
    if (!existing.expiresAt) {
      return {
        success: false,
        message: 'Expiry time not found for this OTP.',
      };
    }

    const expiresAt = new Date(existing.expiresAt);
    const now = new Date();

    // ✅ Validate if `expiresAt` is a valid date
    if (isNaN(expiresAt.getTime())) {
      return {
        success: false,
        message: 'Invalid expiry date format.',
      };
    }

    if (now > expiresAt) {
      return {
        success: false,
        message: 'OTP has expired.',
      };
    }

    // ✅ Optionally mark the OTP as used (optional step)
    // await this.otpVerificationRepository.updateById(existing.id, {is_used: true});

    return {
      success: true,
      message: 'OTP verified successfully.',
    };
  }

  @post('/otp-verifications/check-user')
  @response(200, {
    description: 'Check if phone exists in Buyer or Seller',
    content: {
      'application/json': {
        schema: {
          type: 'object',
          properties: {
            source: {type: 'string'}, // 'buyer' | 'seller' | 'none'
            data: {type: 'object'},
          },
        },
      },
    },
  })
  async checkUser(
    @requestBody({
      content: {
        'application/json': {
          schema: {
            type: 'object',
            properties: {
              phone_number: {type: 'string'},
            },
            required: ['phone_number'],
          },
        },
      },
    })
    body: {phone_number: string},
  ): Promise<{source: 'buyer' | 'seller' | 'none'; data: any | null}> {
    const {phone_number} = body;
    console.log('Checking user for phone:', phone_number);
    // Check seller table
    const seller = await this.sellerRepository.findOne({
      where: {sellerMobile: phone_number.trim()},
    });
    console.log(seller)
    if (seller) {
      return {source: 'seller', data: seller};
    }

    // Check buyer table
    const buyer = await this.buyerRepository.findOne({
      where: {buyerMobile: phone_number.trim()},
    });
    console.log(buyer)
    if (buyer) {
      return {source: 'buyer', data: buyer};
    }


    // No match
    return {source: 'none', data: null};
  }

  @get('/otp-verifications')
  @response(200, {
    description: 'Array of OtpVerification model instances',
    content: {
      'application/json': {
        schema: {
          type: 'array',
          items: getModelSchemaRef(OtpVerification, {includeRelations: true}),
        },
      },
    },
  })
  async find(
    @param.filter(OtpVerification) filter?: Filter<OtpVerification>,
  ): Promise<OtpVerification[]> {
    return this.otpVerificationRepository.find(filter);
  }

  @patch('/otp-verifications')
  @response(200, {
    description: 'OtpVerification PATCH success count',
    content: {'application/json': {schema: CountSchema}},
  })
  async updateAll(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(OtpVerification, {partial: true}),
        },
      },
    })
    otpVerification: OtpVerification,
    @param.where(OtpVerification) where?: Where<OtpVerification>,
  ): Promise<Count> {
    return this.otpVerificationRepository.updateAll(otpVerification, where);
  }

  @get('/otp-verifications/{id}')
  @response(200, {
    description: 'OtpVerification model instance',
    content: {
      'application/json': {
        schema: getModelSchemaRef(OtpVerification, {includeRelations: true}),
      },
    },
  })
  async findById(
    @param.path.number('id') id: number,
    @param.filter(OtpVerification, {exclude: 'where'}) filter?: FilterExcludingWhere<OtpVerification>
  ): Promise<OtpVerification> {
    return this.otpVerificationRepository.findById(id, filter);
  }

  @patch('/otp-verifications/{id}')
  @response(204, {
    description: 'OtpVerification PATCH success',
  })
  async updateById(
    @param.path.number('id') id: number,
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(OtpVerification, {partial: true}),
        },
      },
    })
    otpVerification: OtpVerification,
  ): Promise<void> {
    await this.otpVerificationRepository.updateById(id, otpVerification);
  }

  @put('/otp-verifications/{id}')
  @response(204, {
    description: 'OtpVerification PUT success',
  })
  async replaceById(
    @param.path.number('id') id: number,
    @requestBody() otpVerification: OtpVerification,
  ): Promise<void> {
    await this.otpVerificationRepository.replaceById(id, otpVerification);
  }

  @del('/otp-verifications/{id}')
  @response(204, {
    description: 'OtpVerification DELETE success',
  })
  async deleteById(@param.path.number('id') id: number): Promise<void> {
    await this.otpVerificationRepository.deleteById(id);
  }
}
