syntax = "proto3";

package commission;

import "public_messages.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/timestamp.proto";
import "google/api/annotations.proto";

option csharp_namespace = "CMSMicroservice.Protobuf.Protos.Commission";

service CommissionContract
{
    // Commands
    rpc CalculateWeeklyBalances(CalculateWeeklyBalancesRequest) returns (google.protobuf.Empty){
        option (google.api.http) = {
            post: "/Commission/CalculateWeeklyBalances"
            body: "*"
        };
    };
    rpc CalculateWeeklyCommissionPool(CalculateWeeklyCommissionPoolRequest) returns (google.protobuf.Empty){
        option (google.api.http) = {
            post: "/Commission/CalculateWeeklyPool"
            body: "*"
        };
    };
    rpc ProcessUserPayouts(ProcessUserPayoutsRequest) returns (google.protobuf.Empty){
        option (google.api.http) = {
            post: "/Commission/ProcessPayouts"
            body: "*"
        };
    };
    rpc RequestWithdrawal(RequestWithdrawalRequest) returns (google.protobuf.Empty){
        option (google.api.http) = {
            post: "/Commission/RequestWithdrawal"
            body: "*"
        };
    };
    rpc ProcessWithdrawal(ProcessWithdrawalRequest) returns (google.protobuf.Empty){
        option (google.api.http) = {
            post: "/Commission/ProcessWithdrawal"
            body: "*"
        };
    };
    
    // Queries
    rpc GetWeeklyCommissionPool(GetWeeklyCommissionPoolRequest) returns (GetWeeklyCommissionPoolResponse){
        option (google.api.http) = {
            get: "/Commission/GetWeeklyPool"
        };
    };
    rpc GetUserCommissionPayouts(GetUserCommissionPayoutsRequest) returns (GetUserCommissionPayoutsResponse){
        option (google.api.http) = {
            get: "/Commission/GetUserPayouts"
        };
    };
    rpc GetCommissionPayoutHistory(GetCommissionPayoutHistoryRequest) returns (GetCommissionPayoutHistoryResponse){
        option (google.api.http) = {
            get: "/Commission/GetPayoutHistory"
        };
    };
    rpc GetUserWeeklyBalances(GetUserWeeklyBalancesRequest) returns (GetUserWeeklyBalancesResponse){
        option (google.api.http) = {
            get: "/Commission/GetUserWeeklyBalances"
        };
    };
    rpc GetAllWeeklyPools(GetAllWeeklyPoolsRequest) returns (GetAllWeeklyPoolsResponse){
        option (google.api.http) = {
            get: "/Commission/GetAllWeeklyPools"
        };
    };
    rpc GetWithdrawalRequests(GetWithdrawalRequestsRequest) returns (GetWithdrawalRequestsResponse){
        option (google.api.http) = {
            get: "/Commission/GetWithdrawalRequests"
        };
    };
    rpc ApproveWithdrawal(ApproveWithdrawalRequest) returns (google.protobuf.Empty){
        option (google.api.http) = {
            post: "/Commission/ApproveWithdrawal"
            body: "*"
        };
    };
    rpc RejectWithdrawal(RejectWithdrawalRequest) returns (google.protobuf.Empty){
        option (google.api.http) = {
            post: "/Commission/RejectWithdrawal"
            body: "*"
        };
    };
    
    // Worker Control APIs
    rpc TriggerWeeklyCalculation(TriggerWeeklyCalculationRequest) returns (TriggerWeeklyCalculationResponse){
        option (google.api.http) = {
            post: "/Commission/TriggerCalculation"
            body: "*"
        };
    };
    rpc GetWorkerStatus(GetWorkerStatusRequest) returns (GetWorkerStatusResponse){
        option (google.api.http) = {
            get: "/Commission/GetWorkerStatus"
        };
    };
    rpc GetWorkerExecutionLogs(GetWorkerExecutionLogsRequest) returns (GetWorkerExecutionLogsResponse){
        option (google.api.http) = {
            get: "/Commission/GetWorkerLogs"
        };
    };
    rpc GetAvailableWeeks(GetAvailableWeeksRequest) returns (GetAvailableWeeksResponse){
        option (google.api.http) = {
            get: "/Commission/GetAvailableWeeks"
        };
    };

    // Week Definitions (for dropdowns)
    rpc GetWeekDefinitions(GetWeekDefinitionsRequest) returns (GetWeekDefinitionsResponse){
        option (google.api.http) = {
            get: "/Commission/GetWeekDefinitions"
        };
    };
    
    // Customer-facing APIs
    rpc GetMyCommissionPayouts(GetMyCommissionPayoutsRequest) returns (GetMyCommissionPayoutsResponse){
        option (google.api.http) = {
            get: "/Commission/Customer/MyPayouts"
        };
    };
    
    rpc GetMyWeeklyBalances(GetMyWeeklyBalancesRequest) returns (GetMyWeeklyBalancesResponse){
        option (google.api.http) = {
            get: "/Commission/Customer/MyWeeklyBalances"
        };
    };

    // Financial Reports
    rpc GetWithdrawalReports(GetWithdrawalReportsRequest) returns (GetWithdrawalReportsResponse){
        option (google.api.http) = {
            get: "/Commission/GetWithdrawalReports"
        };
    };

    // Bulk credit wallet for all Pending payouts of a week
    rpc BulkCreditPayouts(BulkCreditPayoutsRequest) returns (BulkCreditPayoutsResponse){
        option (google.api.http) = {
            post: "/Commission/BulkCreditPayouts"
            body: "*"
        };
    };
}

// ============ Commands ============

// CalculateWeeklyBalances Command
message CalculateWeeklyBalancesRequest
{
  int64 week_definition_id = 1; // Format: "YYYY-Www" (e.g., "2025-W01")
    bool force_recalculate = 2;
}

// CalculateWeeklyCommissionPool Command
message CalculateWeeklyCommissionPoolRequest
{
    int64 week_definition_id = 1;
}

// ProcessUserPayouts Command
message ProcessUserPayoutsRequest
{
    int64 week_definition_id = 1;
    bool force_reprocess = 2;
}

// RequestWithdrawal Command
message RequestWithdrawalRequest
{
    int64 payout_id = 1;
    int32 withdrawal_method = 2; // WithdrawalMethod enum: Cash=0, Diamond=1
    google.protobuf.StringValue iban_number = 3; // Required for Cash method
}

// ProcessWithdrawal Command
message ProcessWithdrawalRequest
{
    int64 payout_id = 1;
    bool is_approved = 2;
    google.protobuf.StringValue reason = 3; // Required for rejection
}

// ApproveWithdrawal Command
message ApproveWithdrawalRequest
{
    int64 payout_id = 1;
    google.protobuf.StringValue notes = 2; // Optional admin notes
}

// RejectWithdrawal Command
message RejectWithdrawalRequest
{
    int64 payout_id = 1;
    string reason = 2; // Required reason for rejection
}

// ============ Queries ============

// GetWeeklyCommissionPool Query
message GetWeeklyCommissionPoolRequest
{
    int64 week_definition_id = 1;
    google.protobuf.Int64Value package_id = 2; // اگر خالی باشد اولین pool هفته را برمی‌گرداند
}

message GetWeeklyCommissionPoolResponse
{
    int64 id = 1;
    int64 week_definition_id = 2;
    int64 total_pool_amount = 4; // Rials
    int32 total_balances = 5;
    int64 value_per_balance = 6; // Rials per balance
    bool is_calculated = 7;
    google.protobuf.Timestamp calculated_at = 8;
    google.protobuf.Timestamp created = 9;
    int64 package_id = 10;
    string package_title = 11;
    // Q29: اعتبارسنجی TotalPoolAmount
    bool validation_is_valid = 12;
    int64 validation_expected_amount = 13;
    int64 validation_discrepancy = 14;
    int32 validation_activation_count = 15;
}

// GetUserCommissionPayouts Query
message GetUserCommissionPayoutsRequest
{
    google.protobuf.Int64Value user_id = 1;
    google.protobuf.Int32Value status = 2; // CommissionPayoutStatus enum
    google.protobuf.Int64Value week_definition_id = 3; // Preferred filter
    google.protobuf.Int64Value package_id = 4; // فیلتر بر اساس پکیج
    int32 page_index = 5;
    int32 page_size = 6;
}

message GetUserCommissionPayoutsResponse
{
    messages.MetaData meta_data = 1;
    repeated UserCommissionPayoutModel models = 2;
}

message UserCommissionPayoutModel
{
  int64 id = 1;
  int64 week_definition_id = 2;
  int64 user_id = 3;
  string user_name = 4;
  string week_display_name = 5;
  int64 weekly_pool_id = 6;
  int64 balances_earned = 7;
  int64 value_per_balance = 8;
  int64 total_amount = 9;
  int32 status = 10; // CommissionPayoutStatus enum
  google.protobuf.Timestamp paid_at = 11;
  google.protobuf.Int32Value withdrawal_method = 12;
  string iban_number = 13;
  google.protobuf.Timestamp withdrawn_at = 14;
  google.protobuf.Timestamp created = 15;
  int64 package_id = 16; // شناسه پکیج
  string package_title = 17; // نام پکیج
}

// GetCommissionPayoutHistory Query
message GetCommissionPayoutHistoryRequest
{
    google.protobuf.Int64Value payout_id = 1;
    google.protobuf.Int64Value user_id = 2;
    google.protobuf.Int64Value week_definition_id = 3; // Preferred filter
    int32 page_index = 5;
    int32 page_size = 6;
}

message GetCommissionPayoutHistoryResponse
{
    messages.MetaData meta_data = 1;
    repeated CommissionPayoutHistoryModel models = 2;
}

message CommissionPayoutHistoryModel
{
    int64 id = 1;
    int64 payout_id = 2;
    int64 user_id = 3;
    int64 week_definition_id = 4;
    int64 amount_before = 6;
    int64 amount_after = 7;
    int32 old_status = 8; // CommissionPayoutStatus enum
    int32 new_status = 9;
    int32 action = 10; // CommissionPayoutAction enum
    string performed_by = 11;
    string reason = 12;
    google.protobuf.Timestamp created = 13;
}

// ============ GetAvailableWeeks ============

message GetAvailableWeeksRequest
{
    int32 future_weeks_count = 1; // تعداد هفته‌های آینده (پیش‌فرض: 4)
    int32 past_weeks_count = 2;   // تعداد هفته‌های گذشته (پیش‌فرض: 12)
}

message GetAvailableWeeksResponse
{
    WeekInfo current_week = 1;
    repeated WeekInfo calculated_weeks = 2;
    repeated WeekInfo pending_weeks = 3;
    repeated WeekInfo future_weeks = 4;
}

message WeekInfo
{
    int64 week_definition_id = 1;       // FK to WeekDefinition
    string display_name = 2;
    google.protobuf.Timestamp start_date = 3;
    google.protobuf.Timestamp end_date = 4;
    bool is_calculated = 5;
    google.protobuf.Timestamp calculated_at = 6;
    string last_execution_status = 7;
    int64 total_pool_amount = 8;
    int32 eligible_users_count = 9;
    string display_text = 10;            // نمایش فارسی برای UI
}


// GetUserWeeklyBalances Query
message GetUserWeeklyBalancesRequest
{
    google.protobuf.Int64Value user_id = 1;
    google.protobuf.Int64Value week_definition_id = 2; // Preferred filter
    google.protobuf.Int64Value package_id = 3; // فیلتر بر اساس پکیج
    bool only_active = 4; // Only non-expired balances
    int32 page_index = 5;
    int32 page_size = 6;
}

message GetUserWeeklyBalancesResponse
{
    messages.MetaData meta_data = 1;
    repeated UserWeeklyBalanceModel models = 2;
}

message UserWeeklyBalanceModel
{
    int64 id = 1;
    int64 user_id = 2;
    string user_full_name = 3; // نام کامل کاربر
    int64 week_definition_id = 4;
    string week_display_name = 5;
    int32 left_leg_new_members = 6; // اعضای جدید چپ این هفته
    int32 left_leg_carryover = 7; // باقیمانده چپ از هفته قبل
    int32 left_leg_total = 8; // مجموع چپ (NewMembers + Carryover)
    int32 right_leg_new_members = 9; // اعضای جدید راست این هفته
    int32 right_leg_carryover = 10; // باقیمانده راست از هفته قبل
    int32 right_leg_total = 11; // مجموع راست (NewMembers + Carryover)
    int32 total_balances = 12; // تعداد تعادل = MIN(چپ, راست)
    int64 weekly_pool_contribution = 13;
    google.protobuf.Timestamp calculated_at = 14;
    bool is_expired = 15;
    google.protobuf.Timestamp created = 16;
    int64 package_id = 17; // شناسه پکیج
    string package_title = 18; // نام پکیج
}

// GetAllWeeklyPools Query
message GetAllWeeklyPoolsRequest
{
    google.protobuf.Int64Value from_week_definition_id = 1; // WeekDefinitionId filter (optional)
    google.protobuf.Int64Value to_week_definition_id = 2;   // WeekDefinitionId filter (optional)
    google.protobuf.BoolValue only_calculated = 3; // Only show calculated pools
    google.protobuf.Int64Value package_id = 4; // فیلتر بر اساس پکیج (optional)
    int32 page_index = 5;
    int32 page_size = 6;
}

message GetAllWeeklyPoolsResponse
{
    messages.MetaData meta_data = 1;
    repeated WeeklyCommissionPoolModel models = 2;
}

message WeeklyCommissionPoolModel
{
    int64 id = 1;
    int64 week_definition_id = 2;
    string week_display_name = 3;
    int64 total_pool_amount = 4;
    int32 total_balances = 5;
    int64 value_per_balance = 6;
    bool is_calculated = 7;
    google.protobuf.Timestamp calculated_at = 8;
    google.protobuf.Timestamp created = 9;
    int64 package_id = 10;
    string package_title = 11;
}

// GetWithdrawalRequests Query
message GetWithdrawalRequestsRequest
{
    google.protobuf.Int32Value status = 1; // CommissionPayoutStatus enum: Pending=1, Approved=2, Rejected=3
    google.protobuf.Int64Value user_id = 2;
    google.protobuf.Int64Value week_definition_id = 3; // Preferred filter
    int32 page_index = 5;
    int32 page_size = 6;
    string iban_number = 7;
}

message GetWithdrawalRequestsResponse
{
    messages.MetaData meta_data = 1;
    repeated WithdrawalRequestModel models = 2;
}

// ============ Worker Control APIs ============

// TriggerWeeklyCalculation Command
message TriggerWeeklyCalculationRequest
{
    int64 week_definition_id = 1; // Format: "YYYY-Www" (e.g., "2025-W48")
    bool force_recalculate = 2; // اگر true باشد، محاسبات قبلی را حذف و دوباره محاسبه می‌کند
    bool skip_balances = 3; // Skip balance calculation (only pool and payouts)
    bool skip_pool = 4; // Skip pool calculation (only balances and payouts)
    bool skip_payouts = 5; // Skip payout processing (only balances and pool)
    google.protobuf.Int64Value package_id = 6; // اگر مقدار دارد فقط این پکیج محاسبه می‌شود - در غیر این صورت همه پکیج‌ها
}

message TriggerWeeklyCalculationResponse
{
    bool success = 1;
    string message = 2;
    string execution_id = 3; // Unique ID for tracking this execution
    google.protobuf.Timestamp started_at = 4;
}

// GetWorkerStatus Query
message GetWorkerStatusRequest
{
    // Empty - returns current worker status
}

message GetWorkerStatusResponse
{
    bool is_running = 1;
    bool is_enabled = 2;
    google.protobuf.StringValue current_execution_id = 3;
    google.protobuf.StringValue current_week_number = 4;
    google.protobuf.StringValue current_step = 5; // "Balances" | "Pool" | "Payouts" | "Idle"
    google.protobuf.Timestamp last_run_at = 6;
    google.protobuf.Timestamp next_scheduled_run = 7;
    int32 total_executions = 8;
    int32 successful_executions = 9;
    int32 failed_executions = 10;
}

// GetWorkerExecutionLogs Query
message GetWorkerExecutionLogsRequest
{
    google.protobuf.Int64Value week_definition_id = 1; // Preferred filter
    google.protobuf.StringValue execution_id = 3; // Filter by specific execution
    google.protobuf.BoolValue success_only = 4; // Show only successful runs
    google.protobuf.BoolValue failed_only = 5; // Show only failed runs
    int32 page_index = 6;
    int32 page_size = 7;
}

message GetWorkerExecutionLogsResponse
{
    messages.MetaData meta_data = 1;
    repeated WorkerExecutionLogModel models = 2;
}

message WorkerExecutionLogModel
{
    string execution_id = 1;
    int64 week_definition_id = 2;
    string week_display_name = 3;
    string step = 4; // "Balances" | "Pool" | "Payouts" | "Full"
    bool success = 5;
    google.protobuf.StringValue error_message = 6;
    google.protobuf.Timestamp started_at = 7;
    google.protobuf.Timestamp completed_at = 8;
    int64 duration_ms = 9; // Duration in milliseconds
    int32 records_processed = 10;
    google.protobuf.StringValue details = 11; // JSON or text details
}

// GetWithdrawalReports Query
message GetWithdrawalReportsRequest
{
    google.protobuf.Timestamp start_date = 1; // Optional - default: 30 days ago
    google.protobuf.Timestamp end_date = 2;   // Optional - default: today
    int32 period_type = 3; // ReportPeriodType: Daily=1, Weekly=2, Monthly=3
    google.protobuf.Int32Value status = 4; // CommissionPayoutStatus enum (optional)
    google.protobuf.Int64Value user_id = 5; // Optional user filter
}

message GetWithdrawalReportsResponse
{
    repeated PeriodReport period_reports = 1;
    WithdrawalSummary summary = 2;
}

message PeriodReport
{
    string period_label = 1; // e.g., "2025-01-15", "هفته 3", "فروردین 1404"
    google.protobuf.Timestamp start_date = 2;
    google.protobuf.Timestamp end_date = 3;
    int32 total_requests = 4;
    int32 pending_count = 5;
    int32 approved_count = 6;
    int32 rejected_count = 7;
    int32 completed_count = 8;
    int32 failed_count = 9;
    int64 total_amount = 10;
    int64 paid_amount = 11;
    int64 pending_amount = 12;
}

message WithdrawalSummary
{
    int32 total_requests = 1;
    int64 total_amount = 2;
    int64 total_paid = 3;
    int64 total_pending = 4;
    int64 total_rejected = 5;
    int64 average_amount = 6;
    int32 unique_users = 7;
    float success_rate = 8; // Percentage (0-100)
}

message WithdrawalRequestModel
{
    int64 id = 1;
    int64 user_id = 2;
    string user_name = 3;
    int64 week_definition_id = 4;
    int64 amount = 6;
    int32 status = 7; // CommissionPayoutStatus enum
    int32 withdrawal_method = 8; // WithdrawalMethod enum
    string iban_number = 9;
    google.protobuf.Timestamp requested_at = 10;
    google.protobuf.Timestamp processed_at = 11;
    string processed_by = 12;
    string reason = 13;
    google.protobuf.Timestamp created = 14;
    string bank_reference_id = 15;
    string bank_tracking_code = 16;
    string payment_failure_reason = 17;
    google.protobuf.StringValue package_name = 18; // نام پکیج کاربر
}

// ============ Week Definitions (for dropdowns) ============

// GetWeekDefinitions Query - برای دریافت لیست هفته‌ها برای dropdown
message GetWeekDefinitionsRequest
{
    //موقعیت صفحه بندی 
    messages.PaginationState pagination_state = 1;
    //مرتب سازی بر اساس 
    google.protobuf.StringValue sort_by = 2;
    //فیلتر 
    GetWeekDefinitionsFilter filter = 3;
    
    // Frontend compatibility fields (aliases)
    int32 page_number = 20;
    int32 page_size = 21;
    string search_text = 22;
    google.protobuf.Int32Value gregorian_year = 23;
    google.protobuf.Int32Value persian_year = 24;
    google.protobuf.BoolValue is_active = 25;
}

message GetWeekDefinitionsFilter
{
    //جستجوی متنی روی DisplayName
    google.protobuf.StringValue search_text = 1;
    //شماره ترتیب هفته
    google.protobuf.Int32Value week_order = 2;
    //شماره هفته میلادی
    google.protobuf.StringValue gregorian_week_number = 3;
    //شماره هفته شمسی
    google.protobuf.StringValue persian_week_number = 4;
    //سال میلادی
    google.protobuf.Int32Value gregorian_year = 5;
    //سال شمسی
    google.protobuf.Int32Value persian_year = 6;
    //فقط هفته‌های فعال
    google.protobuf.BoolValue is_active = 7;
}

message GetWeekDefinitionsResponse
{
    repeated WeekDefinitionItem data = 1;
    int32 total_count = 2;
}

message WeekDefinitionItem
{
    int64 id = 1; // WeekDefinitionId
    int32 week_order = 2;
    string display_name = 3; // هفته یکم، هفته دوم، ...
    string gregorian_week_number = 4; // 2025-W46
    string persian_week_number = 5; // 1404-W35
    google.protobuf.Timestamp start_date = 6;
    google.protobuf.Timestamp end_date = 7;
    int32 gregorian_year = 8;
    int32 persian_year = 9;
    bool is_active = 10;
    bool is_current_week = 11;
    string start_date_persian = 12; // Frontend expects Persian date string
    string end_date_persian = 13; // Frontend expects Persian date string
}

// BulkCreditPayouts Command
message BulkCreditPayoutsRequest
{
    int64 week_definition_id = 1; // Credit all Pending payouts for this week
}

message BulkCreditPayoutsResponse
{
    int32 credited_count = 1;   // تعداد پرداخت‌هایی که به کیف پول واریز شد
    int64 total_credited = 2;   // مجموع مبلغ واریز شده (ریال)
    string message = 3;
}

// ============ Customer APIs ============

// GetMyCommissionPayouts - for frontend customer display
message GetMyCommissionPayoutsRequest
{
    int32 page_number = 1;
    int32 page_size = 2;
    google.protobuf.Int64Value week_definition_id = 3;
    google.protobuf.Int32Value status = 4; // 0=Pending, 1=Calculated, 2=Paid, 3=Withdrawn
    google.protobuf.Int64Value package_id = 5; // فیلتر بر اساس پکیج
}

message GetMyCommissionPayoutsResponse
{
    CustomerMetaData meta_data = 1;
    repeated CustomerCommissionPayoutModel payouts = 2;
}

message CustomerMetaData
{
    int64 total_count = 1;
}

message CustomerCommissionPayoutModel
{
    int64 id = 1;
    int64 week_definition_id = 2;
    string week_display_name = 3;
    int32 balances_earned = 4;
    int64 total_amount = 5;
    string amount_formatted = 6;
    int32 status = 7;  // 0=Pending, 1=Paid, 2=WithdrawRequested, 3=Withdrawn, 4=PaymentFailed, 5=Cancelled
    google.protobuf.Timestamp calculated_date = 8;
    string date_persian = 9;
    int64 package_id = 10; // شناسه پکیج
    string package_title = 11; // نام پکیج
}

// GetMyWeeklyBalances - for frontend customer display
message GetMyWeeklyBalancesRequest
{
    int32 page_number = 1;
    int32 page_size = 2;
    google.protobuf.Int64Value week_definition_id = 3;
    bool only_active = 4;
    google.protobuf.Int64Value package_id = 5; // فیلتر بر اساس پکیج
}

message GetMyWeeklyBalancesResponse
{
    CustomerMetaData meta_data = 1;
    repeated CustomerWeeklyBalanceModel balances = 2;
    int32 total_left_balances = 3;
    int32 total_right_balances = 4;
    string weaker_leg = 5;
}

message CustomerWeeklyBalanceModel
{
    int64 id = 1;
    int64 week_definition_id = 2;
    string week_display_name = 3;
    int32 left_leg_balances = 4;
    int32 right_leg_balances = 5;
    int32 total_balances = 6;
    int64 weekly_pool_contribution = 7;
    bool is_expired = 8;
    google.protobuf.Timestamp calculated_at = 9;
    string date_persian = 10;
    int32 left_leg_carryover = 11;
    int32 right_leg_carryover = 12;
    int32 left_leg_new_members = 13;
    int32 right_leg_new_members = 14;
    int64 package_id = 15; // شناسه پکیج
    string package_title = 16; // نام پکیج
}
