using System.ComponentModel.DataAnnotations;
using DateTimeConverterCL;
using CMSMicroservice.Protobuf.Protos.User;
using FrontOffice.Main.Shared;
using FrontOffice.Main.Utilities;
using Google.Protobuf.WellKnownTypes;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using MudBlazor;
using Blazored.LocalStorage;

namespace FrontOffice.Main.Pages;

public partial class RegisterWizard
{
    [Inject] private UserContract.UserContractClient UserContract { get; set; } = default!;

    private readonly RegistrationModel _model = new();
    private MudForm? _stepTwoForm;
    private MudForm? _stepThreeForm;
    private int _activeStep;
    private bool _isSubmitting;
    private bool _completed;
    private AuthDialog? _authDialog;
    private MudStepper? _mudStepper;
    private UpdateCustomerProfileRequest _updateUserRequest = new();
    private bool _isAuthenticated;
    private CancellationTokenSource? _operationCts;
    private UserAuthInfo _userAuthInfo;
    private Guid signGuid = Guid.NewGuid();
    private const string TokenStorageKey = "auth:token";
    private readonly DialogOptions _normalWidth = new() { MaxWidth = MaxWidth.ExtraSmall, FullWidth = true };
    private bool _initialDataLoaded;

    [Inject] private AuthService AuthService { get; set; } = default!;
    [Inject] private IDeviceDetector _deviceDetector { get; set; } = default!;
    [Inject] private IJSRuntime Js { get; set; } = default!;
    [Inject] private ILocalStorageService LocalStorage { get; set; } = default!;
    [Inject] private UserContract.UserContractClient UserClient { get; set; } = default!;


    private string _nextButtonText => _activeStep switch
    {
        0 => "ادامه",
        1 => "ادامه",
        _ => _isSubmitting ? "در حال ارسال..." : "ثبت نهایی"
    };


    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        _isAuthenticated = await AuthService.IsAuthenticatedAsync();
        if (_isAuthenticated)
        {
            _userAuthInfo = await AuthService.GetUserAuthInfo();
            if (_userAuthInfo.IsSignMainContract)
            {
                Navigation.NavigateTo(RouteConstants.Profile.Index);
                return;
            }

            if (_activeStep == 0)
            {
                await _mudStepper.NextStepAsync();
                _activeStep = 1;
                await InvokeAsync(StateHasChanged);
            }
            else if (_activeStep == 1 && !_initialDataLoaded)
            {
                _initialDataLoaded = true;
                try
                {
                    var existUser = await UserContract.GetUserForCustomerAsync(new GetUserForCustomerRequest());
                    if (existUser != null && !string.IsNullOrEmpty(existUser.FirstName) &&
                        string.IsNullOrWhiteSpace(_model.FirstName))
                    {
                        _model.FirstName = existUser.FirstName;
                    }

                    if (existUser != null && !string.IsNullOrEmpty(existUser.LastName) &&
                        string.IsNullOrWhiteSpace(_model.LastName))
                    {
                        _model.LastName = existUser.LastName;
                    }

                    if (existUser != null && !string.IsNullOrEmpty(existUser.NationalCode) &&
                        string.IsNullOrWhiteSpace(_model.NationalCode))
                    {
                        _model.NationalCode = existUser.NationalCode;
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }

                await InvokeAsync(StateHasChanged);
            }
        }

        await base.OnAfterRenderAsync(firstRender);
    }

    private async Task GoBack()
    {
        if (_activeStep == 0 || _isSubmitting || (_isAuthenticated && _activeStep == 1))
            return;

        _activeStep--;
        await _mudStepper.PreviousStepAsync();
    }

    private async Task GoNextAsync()
    {
        if (_isSubmitting)
            return;

        switch (_activeStep)
        {
            case 0:
                if (_authDialog._currentStep == AuthDialog.AuthStep.Phone)
                {
                    try
                    {
                        _isSubmitting = true;
                        await _authDialog.SendOtpAsync();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                        throw;
                    }
                    finally
                    {
                        _isSubmitting = false;
                    }

                    return;
                }
                else
                {
                    try
                    {
                        _isSubmitting = true;
                        var verifyOtp = await _authDialog.VerifyOtpAsync();
                        if (!verifyOtp)
                            return;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                        throw;
                    }
                    finally
                    {
                        _isSubmitting = false;
                    }
                    //continus in OnAfterRenderAsync method
                    //   await _mudStepper.NextStepAsync();
                    //                  _activeStep = 1;
                }

                break;

            case 1:
                if (!await ValidateStepAsync(_stepTwoForm))
                    return;

                var saveResult = await SavePersonalInfo();
                if (!saveResult)
                    return;

                _activeStep = 2;
                await _mudStepper.NextStepAsync();
                break;
            case 2:
                if (!await ValidateStepAsync(_stepThreeForm))
                    return;

                await SubmitAsync();


                break;
        }
    }

    private async Task<bool> ValidateStepAsync(MudForm? form)
    {
        if (form is null)
            return true;

        await form.Validate();
        return form.IsValid;
    }

    private async Task SubmitAsync()
    {
        if (_operationCts == null || _operationCts.IsCancellationRequested)
        {
            _operationCts = new CancellationTokenSource();
        }

        _isSubmitting = true;
        try
        {
            var parameters = new DialogParameters
            {
                { "ContentText", "لطفاً کد تأیید ارسال شده را وارد کنید." },
                { "ButtonText", "تأیید" },
            };
            var options = _deviceDetector.IsMobile()
                ? new DialogOptions() { FullScreen = true}
                : _normalWidth;
            var response = await UserClient.CreateNewOtpTokenAsync(new CreateNewOtpTokenRequest()
            {
                Mobile = _userAuthInfo.MobileNumber,
                Purpose = "signContract",
                SignGuid = signGuid.ToString()
            }, cancellationToken: _operationCts.Token);
            if (response?.Success != true)
            {
                var errorMessage = string.IsNullOrWhiteSpace(response?.Message)
                    ? "ارسال رمز پویا با خطا مواجه شد. لطفاً دوباره تلاش کنید."
                    : response!.Message;
                Snackbar.Add(errorMessage, Severity.Warning);
                return;
            }

            var dialog = await DialogService.ShowAsync<SimpleOtpDialog>("تأیید قرارداد", parameters,options);
            var result = await dialog.Result;
            if (result.Canceled || result.Data is not string otpCode || string.IsNullOrWhiteSpace(otpCode))
            {
                Snackbar.Add("ورود کد تأیید الزامی است.", Severity.Warning);
                return;
            }

            var acceptContractResponse = await UserClient.AcceptContractAsync(new()
            {
                SignGuid = signGuid.ToString(),
                Code = otpCode,
                ContractHtml = GetContractHtml(),
                
            }, cancellationToken: _operationCts.Token);
            if (!string.IsNullOrWhiteSpace(acceptContractResponse.Token))
            {
                await LocalStorage.SetItemAsync(TokenStorageKey, acceptContractResponse.Token);
            }
            else
            {
                await LocalStorage.RemoveItemAsync(TokenStorageKey);
            }


            _completed = true;
            Snackbar.Add("ثبت‌نام اولیه و تأیید قرارداد با موفقیت انجام شد.", Severity.Success);
            await InvokeAsync(StateHasChanged);
            Navigation.NavigateTo(RouteConstants.Profile.Index);
        }
        finally
        {
            _isSubmitting = false;
        }
    }

    private async void DownloadContract()
    {
//var html = $"<!DOCTYPE html><html><body><h1 style='text-align:center'>قرارداد اولیه کاربر</h1><p>نام: {_model.FirstName ?? "-"} {_model.LastName ?? "-"}</p><p>کد ملی: {_model.NationalCode ?? "-"}</p><p>این یک نسخه نمونه است.</p></body></html>";

        var html = GetContractHtml();
        try
        {
// If HTML is short use GET to simplify (URL length safe)
            if (html.Length < 1800)
            {
                var encoded = Uri.EscapeDataString(html);
                Navigation.NavigateTo($"contract/generate?html={encoded}&fileName=sample-contract", true);
                return;
            }

// For larger HTML use POST via JS fetch to stream file
            var fileName = "sample-contract";
            await Js.InvokeVoidAsync("fetchAndDownloadPdf", html, fileName);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"PDF download error: {ex.Message}");
// Fallback to GET (may truncate if too long)
            var encoded = Uri.EscapeDataString(html);
            Navigation.NavigateTo($"contract/generate?html={encoded}&fileName=sample-contract", true);
        }
    }

    private void OnPhoneVerified()
    {
// Move to next step after phone verification success
// _activeStep = 1;
//StateHasChanged();
    }

    public string GetContractHtml()
    {
        var html =
            $"<!DOCTYPE html><html lang='fa' dir='rtl'><head>" +
            "<meta charset='UTF-8' /><title>قرارداد تعهد و سلب مسئولیت کارابازار</title><style>" +
            "body { " +
            " font-family: sans-serif; " +
            " direction: rtl;text-align: justify; " +
            " font-size: 13px;line-height: 1.8; " +
            " margin: 40px;}h1, h2 {text-align: center;margin-bottom: 10px;}" +
            "h1 {font-size: 18px;}h2 {font-size: 15px;}" +
            ".section-title {font-weight: bold;margin-top: 15px;margin-bottom: 5px;}" +
            ".contract-info, .sign-section {margin-top: 20px;}.field-label {font-weight: bold;}" +
            ".box {border: 1px solid #000;padding: 8px;margin-top: 10px;}.small-text {font-size: 11px;line-height: 1.7;}" +
            "</style></head><body><h1>قرارداد تعهد و سلب مسئولیت</h1><h2>بین کارابازار و کاربر</h2><div class='contract-info'>" +
            "<p>این قرارداد تعهد و سلب مسئولیت (&laquo;قرارداد&raquo;) در تاریخ " +
            $"<span class='field-label'>{DateTime.Now.MiladiToJalali()} </span>بین:</p><p>" +
            "1. شرکت/مجموعه <span class='field-label'>کارابازار</span> (که از این پس &laquo;کارابازار&raquo; نامیده می‌شود)،</p><p>2. شخص حقیقی زیر (که از این پس &laquo;کاربر&raquo; نامیده می‌شود):</p><div class='box'>" +
            $"<p><span class='field-label'>نام و نام خانوادگی کاربر:</span> {_model.FirstName} {_model.LastName}</p>" +
            $"<p><span class='field-label'>شماره ملی:</span> {_model.NationalCode?.PersianToEnglish()}</p>" +
            $"<p><span class='field-label'>شماره تماس:</span> {_userAuthInfo.MobileNumber?.PersianToEnglish()}</p></div>" +
            "<p>کارابازار و کاربر که در این قرارداد جداگانه &laquo;طرف&raquo; و مجموعاً &laquo;طرفین&raquo; نامیده می‌شوند، با علم و آگاهی کامل، مفاد زیر را پذیرفته و امضا می‌نمایند.</p></div><div><p class='section-title'>ماده ۱ - موضوع قرارداد</p>" +
            "<p>موضوع این قرارداد، تعیین حدود و چارچوب تعهدات و سلب مسئولیت کارابازار در قبال استفاده کاربر ازخدمات، باشگاه مشتریان، مزایا، طرح‌های همکاری، شبکه معرفی، خرید از فروشگاه‌های طرف‌قراردادو هرگونه امکانات و تسهیلات مرتبط است که حسب مورد توسط کارابازار یا از طریق پلتفرم‌ها و شرکت‌هایهمکار در اختیار کاربر قرار می‌گیرد، بدون اینکه جزئیات مدل کسب‌وکار، شیوه تأمین منابع مالی،شبکه همکاری یا ساختار داخلی آن در این قرارداد ذکر یا افشا شود.</p>" +
            "<p class='section-title'>ماده ۲ - اقرار و آگاهی کاربر</p><p>۲-۱. کاربر اقرار می‌نماید که کلیه اطلاعات کلی لازم در خصوص نحوه فعالیت، مزایا، ریسک‌های احتمالی," +
            "سازوکار کلی استفاده از خدمات، و چارچوب کلی همکاری را از مراجع رسمی معرفی‌شده توسط کارابازاردریافت کرده، سؤالات خود را مطرح نموده و پاسخ مناسب را دریافت نموده است.</p><p>۲-۲. کاربر با امضای این قرارداد اقرار می‌نماید که:</p><ul><li>با اراده آزاد و بدون هرگونه اجبار، اکراه، فریب یا سوءاستفاده از ناآگاهی وارد این همکاری شده است.</li><li>از احتمال وجود ریسک‌های مالی، اعتباری، قانونی و شبکه‌ای مرتبط با فعالیت خود آگاه بوده و آن را می‌پذیرد.</li>" +
            "<li>هرگونه تصمیم برای استفاده از تسهیلات، مزایا، خدمات باشگاه مشتریان، فعالیت در شبکه معرفی، خرید از فروشگاه‌ها و جذب افراد جدید، تصمیمی شخصی و آگاهانه است و به‌عنوان تعهد یا ضمانت بازده مشخص از سوی کارابازار تلقی نمی‌شود.</li></ul>" +
            "<p class='section-title'>ماده ۳ - سلب مسئولیت کارابازار</p><p>۳-۱. کاربر صراحتاً می‌پذیرد که کارابازار صرفاً در چارچوب قوانین و مقررات حاکم و مطابق قراردادها و تفاهم‌نامه‌های خود با شرکای تجاری و پلتفرم‌های همکار، خدمات و امکانات مشخصی را در اختیار کاربر قرار می‌دهد و هیچ‌گونه تعهدی نسبت به:</p><ul><li>تحقق سود یا بازده مالی مشخص،</li><li>ثبات ارزش هرگونه اعتبار، امتیاز، یا منافع غیرنقدی که ممکن است در قالب طرح‌ها به کاربر تخصیص یابد،</li>" +
            "<li>عملکرد اشخاص ثالث (از جمله پلتفرم‌ها، فروشگاه‌ها، شرکت‌های بیمه، ارائه‌دهندگان خدمات سلامت و هر شخص حقیقی یا حقوقی همکار)،</li><li>تصمیمات و اقدامات کاربر در جذب افراد جدید و ایجاد زیرمجموعه،</li></ul><p>نداشته و نخواهد داشت مگر در حدودی که به‌صراحت در قرارداد یا قوانین آمره بر عهده کارابازار گذاشته شده است.</p><p>" +
            "۳-۲. هرگونه خسارت، دعوی، تهدید، مطالبه، ادعا، شکایت یا پیگیری حقوقی که ناشی از تصمیمات شخصی کاربر،نحوه استفاده وی از تسهیلات و مزایا، جذب دیگران، خرید کالا و خدمات، یا تعاملات او با اشخاص ثالث باشد،مستقیماً متوجه خود کاربر است و کارابازار نسبت به آن هیچ‌گونه مسئولیت مدنی، کیفری، مالی یا قراردادی ندارد," +
            "مگر در مواردی که طبق قوانین آمره، مسئولیت صریح و غیرقابل‌اسقاط بر عهده کارابازار قرار گرفته باشد.</p><p>۳-۳. کاربر می‌پذیرد که هیچ‌گونه ادعایی مبنی بر فریب، اغفال، ارائه اطلاعات نادرست یا وعده‌های خارج ازچهارچوب رسمی از سوی کارابازار یا نمایندگان رسمی آن، پس از امضای این قرارداد، از وی مسموع نخواهد بود،مگر آنکه طبق رأی قطعی مرجع قضایی صالح، خلاف آن ثابت شود.</p><p class='section-title'>ماده ۴ - مسئولیت کاربر در قبال تهدید، ادعا و شکایت</p>" +
            "<p>۴-۱. کاربر متعهد است در صورت طرح هرگونه تهدید، ادعا، مطالبه، شکایت یا پیگیری حقوقی از سوی اشخاص ثالث(از جمله افراد جذب‌شده توسط کاربر، زیرمجموعه‌ها، خریداران معرفی‌شده یا سایر اشخاص)، که ناشی از عملکردشخصی کاربر، معرفی‌های وی، شیوه تبلیغ، وعده‌های خارج از چارچوب رسمی کارابازار، یا نقض قوانین و مقرراتباشد، خود رأساً پاسخگو باشد و کارابازار را از هرگونه مسئولیت و هزینه احتمالی در این خصوص مصون بدارد.</p><p>۴-۲. کاربر می‌پذیرد که:</p><ul><li>هرگونه تهدید یا ادعای بی‌جا، غیرمنطقی، غیرمستند یا مغایر با مفاد این قرارداد، متوجه شخص کاربر است.</li>" +
            "<li>در صورت وارد آمدن خسارت مادی یا معنوی به کارابازار ناشی از چنین تهدیدات یا ادعاهایی، کارابازار حق دارد نسبت به مطالبه خسارت از کاربر، طبق قوانین و از طریق مراجع صالح اقدام نماید.</li></ul>" +
            "<p class='section-title'>ماده ۵ - محرمانگی و عدم افشای جزئیات کسب‌وکار</p><p>۵-۱. کاربر می‌پذیرد که جزئیات فنی، مالی، ساختار شبکه، شیوه توزیع مزایا، قراردادهای داخلی کارابازار باشرکای تجاری و پلتفرم‌های همکار، اطلاعات محرمانه تجاری محسوب شده و خارج از این قرارداد است و افشای آن‌هاتوسط کاربر بدون مجوز کتبی کارابازار، مجاز نمی‌باشد.</p><p>۵-۲. کاربر حق استناد به عدم درج جزئیات ساختار کسب‌وکار در این قرارداد را به‌عنوان دلیل بطلان، فسخ یاادعای فریب علیه کارابازار از خود سلب می‌نماید.</p>" +
            "<p class='section-title'>ماده ۶ - کد تأیید یکبارمصرف (OTP) و شناسه قرارداد</p><p>۶-۱. به منظور تأیید هویت کاربر و جایگزین کردن امضا در محیط غیرحضوری، برای این قرارداد یک شناسه یکتا(GUID) تولید شده و از طریق سامانه کارابازار، کد تأیید یکبارمصرف (OTP) مرتبط با آن برای کاربر ارسالمی‌گردد.</p>" +
            "<p>۶-۲. کاربر با وارد کردن صحیح کد تأیید (OTP) در سامانه، اقرار می‌نماید که:</p><ul><li>مالک شماره تماس ثبت‌شده در این قرارداد است یا با اجازه قانونی مالک از آن استفاده می‌کند،</li><li>از محتوای قرارداد به‌طور کامل آگاه است و آن را بدون ابهام و با رضایت کامل می‌پذیرد،</li><li>شناسه یکتا و OTP ارسال‌شده، معادل امضای الکترونیکی معتبر وی بر روی این قرارداد است.</li></ul>" +
            "<p class='section-title'>ماده ۷ - مدت، اصلاح و حاکمیت قانون</p>" +
            "<p>۷-۱. این قرارداد از تاریخ تأیید نهایی (ثبت OTP) نافذ و لازم‌الاجرا بوده و تا زمانی که همکاری کاربر باکارابازار ادامه دارد، معتبر خواهد بود؛ مگر آنکه مطابق قوانین یا توافق طرفین، خاتمه یابد.</p><p>۷-۲. هرگونه اصلاح در مفاد این قرارداد صرفاً از طریق اطلاع‌رسانی رسمی کارابازار و پذیرش کاربر (اعم ازامضای مکتوب، تأیید در سامانه، یا سایر روش‌های الکترونیکی مورد تأیید کارابازار) معتبر خواهد بود.</p><p>۷-۳. این قرارداد از هر حیث، تابع قوانین و مقررات حاکم بر جمهوری اسلامی ایران بوده و در صورت بروز اختلاف،مراجع صالح قضایی محل استقرار کارابازار، صلاحیت رسیدگی خواهند داشت؛ مگر آنکه به نحو دیگری بین طرفین توافقشود." +
            "</p><p class='section-title'>ماده ۸ - اقرار نهایی کاربر</p><p>کاربر با امضای این قرارداد (از طریق ثبت کد تأیید یکبارمصرف OTP متناظر با شناسه یکتا)، صریحاً اعلام می‌نماید که:" +
            "</p><ul><li>کلیه مفاد قرارداد را به‌دقت مطالعه نموده و آن را درک کرده است،</li>" +
            "<li>پرسش‌های خود را مطرح نموده و پاسخ روشن دریافت کرده است،</li><li>ریسک‌ها، محدودیت‌ها و حدود مسئولیت کارابازار را می‌پذیرد،</li><li>حق هرگونه ادعای مغایر با مفاد این قرارداد، به‌ویژه ادعاهای بی‌اساس، غیرمنطقی یا ناشی از برداشت نادرست شخصی را از خود سلب و اسقاط می‌نماید؛ مگر در حدودی که قانون به‌طور آمره اجازه سلب آن را نداده باشد.</li></ul></div><div class='sign-section'></div><p class='small-text'></p><div class='box'><p><span class='field-label'>شناسه یکتای قرارداد :</span></p><p><span id='contract-guid'>" +
            signGuid + "</span></p></div></body></html>";
        return html;
    }

    private async Task<bool> SavePersonalInfo()
    {
        if (_stepTwoForm is null) return false;

        await _stepTwoForm.Validate();
        if (!_stepTwoForm.IsValid) return false;

        _isSubmitting = true;
        try
        {

            _updateUserRequest.FirstName = _model.FirstName;
            _updateUserRequest.LastName = _model.LastName;
            _updateUserRequest.NationalCode = _model.NationalCode.PersianToEnglish();


            await UserContract.UpdateCustomerProfileAsync(request: _updateUserRequest);
            Snackbar.Add("اطلاعات شخصی با موفقیت ذخیره شد.", Severity.Success);
            return true;
        }
        catch (Exception ex)
        {
            Snackbar.Add($"خطا در ذخیره اطلاعات: {ex.Message}", Severity.Error);
            return false;
        }
        finally
        {
            _isSubmitting = false;
            await InvokeAsync(StateHasChanged);
        }
    }

    private sealed class RegistrationModel
    {
        [Required(ErrorMessage = "نام الزامی است.")]
        [StringLength(50, ErrorMessage = "حداکثر ۵۰ کاراکتر")]
        public string? FirstName { get; set; }

        [Required(ErrorMessage = "نام خانوادگی الزامی است.")]
        [StringLength(70, ErrorMessage = "حداکثر ۷۰ کاراکتر")]
        public string? LastName { get; set; }

        [Required(ErrorMessage = "کد ملی الزامی است.")]
        [RegularExpression("^\\d{10}$", ErrorMessage = "کدملی باید ۱۰ رقم باشد.")]
        public string? NationalCode { get; set; }

        [Range(typeof(bool), "true", "true", ErrorMessage = "برای ادامه باید قوانین را تایید کنید.")]
        public bool AcceptTerms { get; set; }
    }
}