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"
        };
    };

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

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

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

// CalculateWeeklyCommissionPool Command
message CalculateWeeklyCommissionPoolRequest
{
    string week_number = 1;
}

// ProcessUserPayouts Command
message ProcessUserPayoutsRequest
{
    string week_number = 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
{
    string week_number = 1;
}

message GetWeeklyCommissionPoolResponse
{
    int64 id = 1;
    string week_number = 2;
    int64 total_pool_amount = 3; // Rials
    int32 total_balances = 4;
    int64 value_per_balance = 5; // Rials per balance
    bool is_calculated = 6;
    google.protobuf.Timestamp calculated_at = 7;
    google.protobuf.Timestamp created = 8;
}

// GetUserCommissionPayouts Query
message GetUserCommissionPayoutsRequest
{
    google.protobuf.Int64Value user_id = 1;
    google.protobuf.Int32Value status = 2; // CommissionPayoutStatus enum
    google.protobuf.StringValue week_number = 3;
    int32 page_index = 4;
    int32 page_size = 5;
}

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

message UserCommissionPayoutModel
{
    int64 id = 1;
    int64 user_id = 2;
    string user_name = 3;
    string week_number = 4;
    int32 balances_earned = 5;
    int64 value_per_balance = 6;
    int64 total_amount = 7;
    int32 status = 8; // CommissionPayoutStatus enum
    google.protobuf.Int32Value withdrawal_method = 9;
    string iban_number = 10;
    google.protobuf.Timestamp created = 11;
    google.protobuf.Timestamp last_modified = 12;
}

// GetCommissionPayoutHistory Query
message GetCommissionPayoutHistoryRequest
{
    google.protobuf.Int64Value payout_id = 1;
    google.protobuf.Int64Value user_id = 2;
    google.protobuf.StringValue week_number = 3;
    int32 page_index = 4;
    int32 page_size = 5;
}

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

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

// GetUserWeeklyBalances Query
message GetUserWeeklyBalancesRequest
{
    google.protobuf.Int64Value user_id = 1;
    google.protobuf.StringValue week_number = 2;
    bool only_active = 3; // Only non-expired balances
    int32 page_index = 4;
    int32 page_size = 5;
}

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

message UserWeeklyBalanceModel
{
    int64 id = 1;
    int64 user_id = 2;
    string week_number = 3;
    int32 left_leg_balances = 4;
    int32 right_leg_balances = 5;
    int32 total_balances = 6;
    int64 weekly_pool_contribution = 7;
    google.protobuf.Timestamp calculated_at = 8;
    bool is_expired = 9;
    google.protobuf.Timestamp created = 10;
}

// GetAllWeeklyPools Query
message GetAllWeeklyPoolsRequest
{
    google.protobuf.StringValue from_week = 1; // Format: "YYYY-Www" (optional)
    google.protobuf.StringValue to_week = 2;   // Format: "YYYY-Www" (optional)
    google.protobuf.BoolValue only_calculated = 3; // Only show calculated pools
    int32 page_index = 4;
    int32 page_size = 5;
}

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

message WeeklyCommissionPoolModel
{
    int64 id = 1;
    string week_number = 2;
    int64 total_pool_amount = 3;
    int32 total_balances = 4;
    int64 value_per_balance = 5;
    bool is_calculated = 6;
    google.protobuf.Timestamp calculated_at = 7;
    google.protobuf.Timestamp created = 8;
}

// 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.StringValue week_number = 3;
    int32 page_index = 4;
    int32 page_size = 5;
    string iban_number = 6;
}

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

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

// TriggerWeeklyCalculation Command
message TriggerWeeklyCalculationRequest
{
    string week_number = 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)
}

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.StringValue week_number = 1; // Filter by week
    google.protobuf.StringValue execution_id = 2; // Filter by specific execution
    google.protobuf.BoolValue success_only = 3; // Show only successful runs
    google.protobuf.BoolValue failed_only = 4; // Show only failed runs
    int32 page_index = 5;
    int32 page_size = 6;
}

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

message WorkerExecutionLogModel
{
    string execution_id = 1;
    string week_number = 2;
    string step = 3; // "Balances" | "Pool" | "Payouts" | "Full"
    bool success = 4;
    google.protobuf.StringValue error_message = 5;
    google.protobuf.Timestamp started_at = 6;
    google.protobuf.Timestamp completed_at = 7;
    int64 duration_ms = 8; // Duration in milliseconds
    int32 records_processed = 9;
    google.protobuf.StringValue details = 10; // 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;
    string week_number = 4;
    int64 amount = 5;
    int32 status = 6; // CommissionPayoutStatus enum
    int32 withdrawal_method = 7; // WithdrawalMethod enum
    string iban_number = 8;
    google.protobuf.Timestamp requested_at = 9;
    google.protobuf.Timestamp processed_at = 10;
    string processed_by = 11;
    string reason = 12;
    google.protobuf.Timestamp created = 13;
    string bank_reference_id = 14;
    string bank_tracking_code = 15;
    string payment_failure_reason = 16;
}
