--======================================================================================================================
-- PROCEDURES
--======================================================================================================================

--1. Трансфер на сметки во иста валута
CREATE OR REPLACE PROCEDURE sp_transfer_same_currency(
    p_amount DECIMAL(20, 2),
    p_from_acc INT,
    p_to_acc INT,
    p_emp_counter INT
)
    LANGUAGE plpgsql AS
$$
DECLARE
    v_ref     VARCHAR(30);
    v_type_id INT;
    v_curr    INT;
BEGIN
    IF NOT fn_is_account_eligible(p_from_acc)
        OR NOT fn_is_account_eligible(p_to_acc) THEN
        RAISE EXCEPTION 'Nevalidni smetki';
    END IF;

    IF (SELECT balance FROM Account WHERE account_id = p_from_acc) < p_amount THEN
        RAISE EXCEPTION 'Nema dovolno sredstva';
    END IF;

    SELECT currency_id
    INTO v_curr
    FROM Account
    WHERE account_id = p_from_acc;

    IF v_curr != (SELECT currency_id
                  FROM Account
                  WHERE account_id = p_to_acc) THEN
        RAISE EXCEPTION 'Valutite ne se isti';
    END IF;

    v_ref := 'TRF-' || TO_CHAR(NOW(), 'YYYYMMDDHH24MISS');

    SELECT transaction_type_id
    INTO v_type_id
    FROM Transaction_type
    WHERE type_name = 'TRANSFER';

    INSERT INTO Transaction(amount, status, reference_number,
                            account_id, account_id2,
                            transaction_type_id,
                            currency_id, currency_id2,
                            emp_counter_id)
    VALUES (p_amount, 'COMPLETED', v_ref,
            p_from_acc, p_to_acc,
            v_type_id,
            v_curr, v_curr,
            p_emp_counter);
END;
$$;

--2. Трансфер на сметки во различна валута
CREATE OR REPLACE PROCEDURE sp_transfer_foreign_currency(
    p_amount DECIMAL(20, 2),
    p_from_acc INT,
    p_to_acc INT,
    p_emp_counter INT
)
    LANGUAGE plpgsql AS
$$
DECLARE
    v_from_curr INT;
    v_to_curr   INT;
    v_ref       VARCHAR(30);
    v_type_id   INT;
BEGIN
    IF NOT fn_is_account_eligible(p_from_acc)
        OR NOT fn_is_account_eligible(p_to_acc) THEN
        RAISE EXCEPTION 'Nevalidni smetki';
    END IF;

    IF (SELECT balance FROM Account WHERE account_id = p_from_acc) < p_amount THEN
        RAISE EXCEPTION 'Nema dovolno sredstva';
    END IF;

    SELECT currency_id
    INTO v_from_curr
    FROM Account
    WHERE account_id = p_from_acc;

    SELECT currency_id
    INTO v_to_curr
    FROM Account
    WHERE account_id = p_to_acc;

    v_ref := 'TRF-' || TO_CHAR(NOW(), 'YYYYMMDDHH24MISS');

    SELECT transaction_type_id
    INTO v_type_id
    FROM Transaction_type
    WHERE type_name = 'TRANSFER';

    INSERT INTO Transaction(amount, status, reference_number,
                            account_id, account_id2,
                            transaction_type_id,
                            currency_id, currency_id2,
                            emp_counter_id)
    VALUES (p_amount, 'COMPLETED', v_ref,
            p_from_acc, p_to_acc,
            v_type_id,
            v_from_curr, v_to_curr,
            p_emp_counter);
END;
$$;


-- 3. Уплата на средства на сметка
CREATE OR REPLACE PROCEDURE sp_deposit(
    p_account_id INT,
    p_amount DECIMAL(20, 2),
    p_currency_id INT,
    p_payment_method INT,
    p_emp_counter_id INT,
    p_description VARCHAR DEFAULT 'Уплата на средства'
)
    LANGUAGE plpgsql AS
$$
DECLARE
    v_deposit_type_id INT;
    v_ref_number      VARCHAR(30);
    v_transaction_id  INT;
BEGIN
    -- Провери дали сметката е активна
    IF NOT fn_is_account_eligible(p_account_id) THEN
        RAISE EXCEPTION 'Smetkata ne e aktivna';
    END IF;

    SELECT transaction_type_id
    INTO v_deposit_type_id
    FROM Transaction_type
    WHERE type_name = 'DEPOSIT';

    v_ref_number := 'TRX-' || LPAD(v_transaction_id::TEXT, 10, '0');

    INSERT INTO Transaction (amount, transaction_date, status, description,
                             reference_number, account_id, transaction_type_id,
                             payment_method_id, currency_id, emp_counter_id)
    VALUES (p_amount, CURRENT_TIMESTAMP, 'COMPLETED', p_description,
            v_ref_number, p_account_id, v_deposit_type_id,
            p_payment_method, p_currency_id, p_emp_counter_id)
    RETURNING transaction_id INTO v_transaction_id;
    -- Тригерот trg_update_account_balance го ажурира балансот
    -- Тригерот trg_auto_generate_receipt генерира Receipt

    RAISE NOTICE 'Уплатата е успешна. Transaction ID: %, Receipt автоматски генериран.', v_transaction_id;
END;
$$;

CALL sp_deposit(1001, 5000.00, 1, 1, 61735);



-- 4. Исплата на средства од сметка
CREATE OR REPLACE PROCEDURE sp_withdraw(
    p_account_id INT,
    p_amount DECIMAL(20, 2),
    p_currency_id INT,
    p_payment_method INT,
    p_emp_counter_id INT,
    p_description VARCHAR DEFAULT 'Исплата на средства'
)
    LANGUAGE plpgsql AS
$$
DECLARE
    v_withdrawal_type_id INT;
    v_ref_number         VARCHAR(30);
    v_current_balance    DECIMAL(20, 2);
    v_transaction_id     INT;
BEGIN
    IF NOT fn_is_account_eligible(p_account_id) THEN
        RAISE EXCEPTION 'Сметката не е активна';
    END IF;


    SELECT balance
    INTO v_current_balance
    FROM Account
    WHERE account_id = p_account_id;

    IF v_current_balance < p_amount THEN
        RAISE EXCEPTION 'Недоволен баланс: тековен=%, побаран=%.',
            v_current_balance, p_amount;
    END IF;

    SELECT transaction_type_id
    INTO v_withdrawal_type_id
    FROM Transaction_type
    WHERE type_name = 'WITHDRAWAL';

    v_ref_number := 'TRX-' || LPAD(v_transaction_id::TEXT, 10, '0');


    INSERT INTO Transaction (amount, transaction_date, status, description,
                             reference_number, account_id, transaction_type_id,
                             payment_method_id, currency_id, emp_counter_id)
    VALUES (p_amount, CURRENT_TIMESTAMP, 'COMPLETED', p_description,
            v_ref_number, p_account_id, v_withdrawal_type_id,
            p_payment_method, p_currency_id, p_emp_counter_id)
    RETURNING transaction_id INTO v_transaction_id;
    -- Тригерот trg_prevent_negative_balance штити од негативен баланс
    -- Тригерот trg_update_account_balance го ажурира балансот

    RAISE NOTICE 'Исплатата е успешна. Transaction ID: %', v_transaction_id;
END;
$$;

CALL sp_withdraw(1001, 1500.00, 1, 1, 61735);
