import {depositAmountRial,type DepositHistory} from './cash-wallet';

export const tomanDepositMethods=['gateway','instant_bank','card_transfer','paya','account_transfer','direct_debit'] as const;
export type TomanDepositMethodId=typeof tomanDepositMethods[number];
export const depositMethodLabels:Record<TomanDepositMethodId,string>={gateway:'درگاه پرداخت',instant_bank:'واریز بانکی آنی',card_transfer:'کارت به کارت',paya:'پایا (شناسه‌دار)',account_transfer:'سپرده به سپرده',direct_debit:'برداشت خودکار'};
export const depositStatusLabels={draft:'پیش‌نویس',submitted:'در انتظار بررسی واریز',cancelled:'لغوشده'};
export type DepositDestination={id:string;version:number;bank_name:string;account_holder:string;iban:string|null;card_number:string|null;account_number:string|null;deposit_identifier:string|null;enabled?:boolean};
export type TomanDepositMethod={id:TomanDepositMethodId;enabled:boolean;reason:string|null;destinations:DepositDestination[]};
export type TomanDepositRequest={id:string;request_id:string;amount_rial:string;method:TomanDepositMethodId;status:keyof typeof depositStatusLabels;version:number;created_at:string;updated_at:string;submitted_at:string|null;cancelled_at:string|null;destination_id?:string|null;destination_version?:number|null;destination?:Omit<DepositDestination,'id'|'version'>|null;bank?:Record<string,unknown>|null;bank_account_id?:string|null;transfer_reference?:string|null};
export type BalePaymentStatus='created'|'pending'|'credited'|'failed'|'cancelled'|'test_paid'|'pending_review';
export type BalePayment={paymentId:string;status:BalePaymentStatus;url:string|null;testMode:boolean;amountRial?:string;expiresAt?:string};
export type TomanDepositState={methods:TomanDepositMethod[];draft:TomanDepositRequest|null;history:TomanDepositRequest[];has_more:boolean;next_cursor:string|null;bank_accounts:{id:string;bank_name:string;iban:string;card_last4:string|null;status:string;eligible:boolean;ownership_checked_at:string|null;card_link_status:string|null}[];limits:{min_amount_rial:string;max_amount_rial:string};deposits:DepositHistory[];enabled?:boolean;provider?:'bale'|null;gateway?:{ready:boolean;testMode:boolean}};

const uuid=(v:unknown):v is string=>typeof v==='string'&&/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(v);
const version=(v:unknown):v is number=>typeof v==='number'&&Number.isSafeInteger(v)&&v>=0&&v<=2147483647;
const object=(v:unknown):v is Record<string,unknown>=>v!==null&&typeof v==='object'&&!Array.isArray(v);
export function baleGatewayInput(value:unknown):Record<string,unknown>{
 if(!object(value))throw new Error('اطلاعات پرداخت معتبر نیست.');
 if(value.action==='start_gateway'&&Object.keys(value).every(k=>['action','requestId','amountToman'].includes(k))&&uuid(value.requestId)){
  const amountRial=depositAmountRial(value.amountToman);
  if(amountRial)return {action:'start',requestId:value.requestId,amountToman:(BigInt(amountRial)/BigInt(10)).toString()};
 }
 if(value.action==='gateway_status'&&Object.keys(value).every(k=>['action','paymentId'].includes(k))&&uuid(value.paymentId))return {action:'status',paymentId:value.paymentId};
 throw new Error('اطلاعات پرداخت معتبر نیست.');
}
/** Only the fixed Bale bot deep link is a customer payment destination. */
export function balePayment(value:unknown):BalePayment|null{
 if(!object(value)||!uuid(value.paymentId)||!['created','pending','credited','failed','cancelled','test_paid','pending_review'].includes(String(value.status))||typeof value.testMode!=='boolean')return null;
 if((value.testMode&&value.status==='credited')||(!value.testMode&&value.status==='test_paid'))return null;
 let url:string|null=null;
 if(value.url!==undefined&&value.url!==null){
  if(typeof value.url!=='string'||value.url.length>512)return null;
  try{const link=new URL(value.url);if(link.protocol!=='https:'||link.hostname!=='ble.ir'||link.port||link.username||link.password||link.hash||!/^\/[A-Za-z0-9_]{3,64}$/.test(link.pathname)||[...link.searchParams.keys()].length!==1||!link.searchParams.has('start')||!/^[A-Za-z0-9_-]{1,128}$/.test(link.searchParams.get('start')||''))return null;url=link.href}catch{return null}
 }
 if(value.amountRial!==undefined&&(typeof value.amountRial!=='string'||!/^\d{1,13}$/.test(value.amountRial)||BigInt(value.amountRial)<=BigInt(0)))return null;
 if(value.expiresAt!==undefined&&(typeof value.expiresAt!=='string'||value.expiresAt.length>50||Number.isNaN(Date.parse(value.expiresAt))))return null;
 return {paymentId:value.paymentId,status:value.status as BalePaymentStatus,url,testMode:value.testMode,...(typeof value.amountRial==='string'?{amountRial:value.amountRial}:{}),...(typeof value.expiresAt==='string'?{expiresAt:value.expiresAt}:{})};
}
export function balePaymentError(code:unknown):[string,number]{
 const errors:Record<string,[string,number]>={test_deposit_limit:['حداکثر پرداخت آزمایشی ۱۰۰ میلیون تومان است.',400],
  unauthorized:['دوباره وارد حساب خود شوید.',401],origin_not_allowed:['این نشانی برای پرداخت فعال نشده است.',403],
  bale_unavailable:['درگاه بله فعلاً در دسترس نیست. کمی بعد دوباره تلاش کنید.',503],bale_not_ready:['درگاه بله هنوز آمادهٔ پرداخت نیست.',503],
  bale_not_configured:['اتصال درگاه بله هنوز تکمیل نشده است.',503],bale_provider_unavailable:['ارتباط با بله برقرار نشد. کمی بعد وضعیت همین درخواست را بررسی کنید.',503],
  invalid_amount:['مبلغ پرداخت باید عدد صحیح مثبت به تومان باشد.',400],invalid_request:['اطلاعات درخواست پرداخت معتبر نیست.',400],bale_verification_mismatch:['اطلاعات پرداخت با درخواست مطابقت ندارد. برای بررسی با پشتیبانی تماس بگیرید.',409],
  gateway_unavailable:['درگاه بله هنوز آمادهٔ پرداخت نیست. بعداً دوباره تلاش کنید.',503],payment_link_expired:['مهلت این درخواست پایان یافته است. وضعیت آن را بررسی و درخواست تازه ایجاد کنید.',409],
  payment_rate_limit:['تعداد درخواست‌ها زیاد است. کمی بعد دوباره تلاش کنید.',429],payment_request_conflict:['این درخواست با مبلغ دیگری ذخیره شده است. ابتدا وضعیت پرداخت قبلی را بررسی کنید.',409],
  payment_not_found:['درخواست پرداخت پیدا نشد.',404],not_authenticated:['دوباره وارد حساب خود شوید.',401],not_authorized:['دسترسی به این درخواست مجاز نیست.',403],
  contact_not_verified:['ابتدا اطلاعات تماس حساب خود را تأیید کنید.',403],identity_required:['ابتدا احراز هویت خود را تکمیل کنید.',403],
  account_suspended:['حساب شما تعلیق شده است. برای پیگیری با پشتیبانی تماس بگیرید.',403],account_deleted:['این حساب بسته شده است.',403],account_closed:['این حساب بسته شده است.',403],
  customer_account_suspended:['حساب شما تعلیق شده است. برای پیگیری با پشتیبانی تماس بگیرید.',403],customer_account_closed:['این حساب بسته شده است.',403],customer_not_found:['حساب کاربری در دسترس نیست.',403],
  payment_payer_conflict:['این درخواست به حساب دیگری در بله متصل شده است. با همان حساب بله ادامه دهید.',409],payment_authority_conflict:['یک پرداخت برای این درخواست در حال پیگیری است. وضعیت همان پرداخت را بررسی کنید.',409],
  payment_verification_mismatch:['اطلاعات پرداخت با درخواست مطابقت ندارد. با پشتیبانی تماس بگیرید.',409],settings_conflict:['تنظیمات درگاه تغییر کرده است. صفحه را تازه‌سازی کنید.',409],
  deposit_identity_required:['ابتدا احراز هویت خود را تکمیل کنید.',403],deposit_verification_required:['ابتدا احراز هویت خود را تکمیل کنید.',403],
  deposit_rate_limit:['تعداد درخواست‌ها زیاد است. کمی بعد دوباره تلاش کنید.',429],deposit_not_found:['درخواست پرداخت پیدا نشد.',404],
  deposit_request_conflict:['مبلغ این درخواست تغییر کرده است. وضعیت پرداخت قبلی را بررسی کنید.',409],bale_payment_expired:['مهلت این پرداخت تمام شده است. درخواست تازه ایجاد کنید.',409],
 };
 return typeof code==='string'&&errors[code]?errors[code]:['وضعیت پرداخت از بله دریافت نشد. پیش از پرداخت دوباره، وضعیت همین درخواست را بررسی کنید.',503];
}
export type TomanDepositInput={rpc:string;params:Record<string,unknown>};
export function tomanDepositInput(value:unknown):TomanDepositInput{
 if(!object(value)||!uuid(value.request_id)||!version(value.version))throw new Error('اطلاعات درخواست معتبر نیست. فرم را تازه‌سازی کنید.');
 const allowed=value.action==='save_draft'?['action','request_id','version','amount_toman','method']:value.action==='cancel'?['action','request_id','version']:value.action==='submit'?['action','request_id','version','destination_id','destination_version','bank_account_id','transfer_reference']:[];
 if(!allowed.length||Object.keys(value).some(k=>!allowed.includes(k)))throw new Error('عملیات واریز معتبر نیست.');
 const params:Record<string,unknown>={p_request:value.request_id,p_version:value.version};
 if(value.action==='save_draft'){
  const rial=depositAmountRial(value.amount_toman);
  if(!rial)throw new Error('مبلغ واریز را به تومان و با عدد صحیح مثبت وارد کنید.');
  if(typeof value.method!=='string'||!tomanDepositMethods.includes(value.method as TomanDepositMethodId)||value.method==='gateway')throw new Error('این روش واریز در دسترس نیست.');
  return {rpc:'marketplace_toman_deposit_save',params:{...params,p_amount_rial:rial,p_method:value.method}};
 }
 if(value.action==='cancel')return {rpc:'marketplace_toman_deposit_cancel',params};
 if(!uuid(value.destination_id)||!uuid(value.bank_account_id)||!version(value.destination_version)||value.destination_version<1||value.version<1||typeof value.transfer_reference!=='string')throw new Error('حساب مبدأ، مقصد و شناسه پیگیری معتبر را وارد کنید.');
 const reference=value.transfer_reference.replace(/[۰-۹]/g,d=>String('۰۱۲۳۴۵۶۷۸۹'.indexOf(d))).replace(/[٠-٩]/g,d=>String('٠١٢٣٤٥٦٧٨٩'.indexOf(d))).trim();
 if(!/^[A-Za-z0-9-]{3,100}$/.test(reference)||!/[A-Za-z0-9]/.test(reference))throw new Error('شناسه پیگیری باید بین ۳ تا ۱۰۰ حرف انگلیسی یا رقم باشد.');
 return {rpc:'marketplace_toman_deposit_submit',params:{...params,p_destination:value.destination_id,p_destination_version:value.destination_version,p_bank:value.bank_account_id,p_transfer_reference:reference}};
}
export function tomanDepositHistoryQuery(url:URL){
 const before=url.searchParams.get('before'),limit=url.searchParams.get('limit');
 if((before!==null&&(before.length<1||before.length>256))||(limit!==null&&!/^(?:[1-9]|[1-9][0-9]|100)$/.test(limit)))throw new Error('صفحهٔ تاریخچه معتبر نیست.');
 return {p_before:before,p_limit:limit?Number(limit):25};
}
export function tomanDepositError(code:string){
 const errors:Record<string,[string,number]>={
  deposit_submission_conflict:['این درخواست قبلاً با اطلاعات دیگری ارسال شده است.',409],deposit_identity_required:['ابتدا احراز هویت خود را تکمیل کنید.',403],deposit_verified_bank_required:['حساب بانکی و مالکیت آن باید تأیید شده باشد.',403],deposit_transfer_reference_used:['این شناسه پیگیری قبلاً ثبت شده است.',409],invalid_deposit_submission:['مشخصات ثبت واریز معتبر نیست.',400],
  not_authenticated:['ابتدا وارد حساب کاربری شوید.',401],not_authorized:['دسترسی به این درخواست مجاز نیست.',403],
  customer_not_found:['حساب کاربری در دسترس نیست.',403],customer_account_suspended:['حساب شما تعلیق شده است.',403],customer_account_closed:['این حساب بسته شده است.',403],
  deposit_method_unavailable:['این روش واریز هنوز فعال نشده است.',409],deposit_not_found:['درخواست واریز پیدا نشد.',404],deposit_version_conflict:['این درخواست تغییر کرده است. تاریخچه را تازه‌سازی کنید.',409],
  deposit_request_conflict:['اطلاعات این درخواست با نسخهٔ ذخیره‌شده متفاوت است. تاریخچه را تازه‌سازی کنید.',409],deposit_draft_exists:['یک پیش‌نویس باز دارید؛ ابتدا همان درخواست را ادامه دهید یا لغو کنید.',409],
  deposit_not_draft:['این درخواست دیگر قابل ویرایش نیست. تاریخچه را تازه‌سازی کنید.',409],deposit_rate_limit:['تعداد درخواست‌ها زیاد است. کمی بعد دوباره تلاش کنید.',429],
  deposit_destination_changed:['اطلاعات حساب مقصد تغییر کرده است. صفحه را تازه‌سازی کنید.',409],deposit_bank_required:['یک حساب بانکی تأییدشده و متعلق به خودتان انتخاب کنید.',400],
  deposit_verification_required:['برای ارسال درخواست واریز ابتدا احراز هویت را تکمیل کنید.',403],invalid_deposit_request:['اطلاعات واریز معتبر نیست.',400],invalid_deposit_filter:['صفحهٔ تاریخچه معتبر نیست.',400],invalid_deposit_input:['اطلاعات واریز معتبر نیست.',400],invalid_deposit_cursor:['تاریخچه را از ابتدا تازه‌سازی کنید.',400],
  PGRST202:['بخش ثبت درخواست واریز هنوز در پایگاه داده فعال نشده است.',503],
 };
 return errors[code]||['ثبت یا دریافت درخواست واریز انجام نشد. تاریخچه را تازه‌سازی کنید و دوباره تلاش کنید.',503];
}
