--the data tables--
drop table users cascade constraints;
drop table categories cascade constraints;
drop table transactions cascade constraints;

--stores the clients info--
create table users (
    user_id int primary key,
    username VARCHAR2(50) not null,
    pwd VARCHAR2(255) not null,
    budget int default (2000) not null ,--pourquoi par default a 2000????????
    balance int default (2000), 
    check(budget >0)
    check(budget >= balance)
);

--stores the clients categories with their info--
CREATE TABLE categories (
    category_id INT PRIMARY KEY,
    user_id INT NOT NULL,
    category_name VARCHAR2(100) NOT NULL,
    amount DECIMAL(10, 2),
    UNIQUE(user_id, category_name),
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);


--stores all the clients transactions--
CREATE TABLE transactions (
    transaction_id int primary key,
    user_id int not null ,
    category_name VARCHAR2(100) NOT NULL,
    category_id int not null,
    expenses DECIMAL(10, 2) NOT NULL,
    descriptions VARCHAR2(255) default("non Précisé"),
    expense_date DATE NOT NULL,
    check (expenses > 0),
    foreign key (user_id) references users(user_id),
    foreign key (category_id) references categories(category_id)
    foreign key (category_name) references categories(category_name)
);

--sequences for our ids values--
drop sequence seq_client_id;
drop sequence seq_categories_id;
drop sequence seq_transaction_id;

create sequence seq_client_id start with 455;
create sequence seq_categories_id start with 1;
create sequence seq_transaction_id start with 1;
/* 
the fonctions(**) and procedures implemented:

    -add_user
    -add_user_no_budget
    -add_category
    -update_category
    -update_category_amount
    -update_category_name_amount
    -add_transaction
    -add_transaction_curr_time
    -add_transaction_no_descrp
    -add_transaction_no_descrp_curr_time
    -get_balance**
    -update_balance
    -add_transaction_and_update_balances


*/
--Add a new client without a budget--
CREATE OR REPLACE PROCEDURE add_user_no_budget(
    p_username users.user_id%type,
    p_pwd users.pwd%type
) AS
BEGIN
    INSERT INTO users (user_id, username, pwd) VALUES (seq_client_id.NEXTVAL, p_username, p_pwd);
END;
/
--Add a new client with a budget--

CREATE OR REPLACE PROCEDURE add_user(
    p_username users.user_id%type,
    p_pwd users.pwd%type, 
    p_budget users.budget%type
) IS
BEGIN
    INSERT INTO users VALUES (seq_client_id.NEXTVAL, p_username, p_pwd, p_budget, p_budget);
END;
/
--add a category--

CREATE OR REPLACE PROCEDURE add_category(
    p_user_id users.user_id%type,
    p_category_name categories.category_id,
    p_amount categories.amount
) IS
BEGIN
    INSERT INTO categories (category_id, user_id, category_name, amount)
    VALUES (seq_categories_id.NEXTVAL, p_user_id, p_category_name, p_amount);
    COMMIT;
END add_category;
/

--update a category changing the name and the amount

CREATE OR REPLACE PROCEDURE update_category_name_amount(
    p_category_id categories.category_id%TYPE,
    p_category_name categories.category_name%TYPE,
    p_amount categories.amount%TYPE
) IS
BEGIN
    UPDATE categories
    SET category_name = p_category_name,
        amount = p_amount
    WHERE category_id = p_category_id;
END;
/

--update a category changing only the amount after a transaction
CREATE OR REPLACE PROCEDURE update_category_amount(
    p_category_id IN categories.category_id%TYPE,
    p_amount IN categories.amount%TYPE
) IS
BEGIN
    UPDATE categories
    SET amount = p_amount
    WHERE category_id = p_category_id;
END;
/
--add a transaction given a date 
CREATE OR REPLACE PROCEDURE add_transaction(
    p_user_id users.user_id%TYPE,
    p_category_name categories.category_name%TYPE,
    p_category_id categories.category_id%TYPE,
    p_expenses transactions.expenses%TYPE,
    p_description transactions.descriptions%TYPE,
    p_expense_date transactions.expense_date%TYPE
) IS
BEGIN
    INSERT INTO transactions (transaction_id, user_id, category_name, category_id, expenses, descriptions, expense_date)
    VALUES (seq_transaction_id.NEXTVAL, p_user_id, p_category_name, p_category_id, p_expenses, p_description, p_expense_date);
END;
/

--add a trasaction actual date--
CREATE OR REPLACE PROCEDURE add_transaction_curr_time(
    p_user_id users.user_id%TYPE,
    p_category_name categories.category_name%TYPE,
    p_category_id categories.category_id%TYPE,
    p_expenses transactions.expenses%TYPE,
    p_description transactions.descriptions%TYPE
) IS
BEGIN
    INSERT INTO transactions (transaction_id, user_id, category_name, category_id, expenses, descriptions, expense_date)
    VALUES (seq_transaction_id.NEXTVAL, p_user_id, p_category_name, p_category_id, p_expenses, p_description, SYSDATE);
END;
/
--add a transaction without a description given a date 
CREATE OR REPLACE PROCEDURE add_transaction_no_descrp(
    p_user_id users.user_id%TYPE,
    p_category_name categories.category_name%TYPE,
    p_category_id categories.category_id%TYPE,
    p_expenses transactions.expenses%TYPE,
    p_expense_date transactions.expense_date%TYPE
) IS
BEGIN
    INSERT INTO transactions (transaction_id, user_id, category_name, category_id, expenses, expense_date)
    VALUES (seq_transaction_id.NEXTVAL, p_user_id, p_category_name, p_category_id, p_expenses, p_expense_date);
END;
/

--add a trasaction  without a description in actual date--
CREATE OR REPLACE PROCEDURE add_transaction_no_descrp_curr_time(
    p_user_id users.user_id%TYPE,
    p_category_name categories.category_name%TYPE,
    p_category_id categories.category_id%TYPE,
    p_expenses transactions.expenses%TYPE,
) IS
BEGIN
    INSERT INTO transactions (transaction_id, user_id, category_name, category_id, expenses, expense_date)
    VALUES (seq_transaction_id.NEXTVAL, p_user_id, p_category_name, p_category_id, p_expenses, SYSDATE);
END;
/

CREATE OR REPLACE FUNCTION get_balance(
    p_user_id IN users.user_id%TYPE
) RETURN users.balance%TYPE
IS v_balance users.balance%TYPE;
BEGIN
    SELECT balance INTO v_balance
    FROM users
    WHERE user_id = p_user_id;
    RETURN v_balance;
END;
/
-- update user balance --
CREATE OR REPLACE PROCEDURE update_balance(
    p_user_id users.user_id%TYPE,
    p_new_balance users.balance%TYPE
) IS
BEGIN
    UPDATE users
    SET balance = p_new_balance
    WHERE user_id = p_user_id;
END update_balance;
/

--add a transaction and apdate the user and category balance 

CREATE OR REPLACE PROCEDURE add_transaction_and_update_balances(
    p_user_id users.user_id%TYPE,
    p_category_name IN categories.category_name%TYPE,
    p_expenses IN transactions.expenses%TYPE,
    p_description IN transactions.descriptions%TYPE
) IS
    v_category_id categories.category_id%TYPE;
    v_new_balance users.balance%TYPE;
BEGIN
    -- Ajouter la transaction
    INSERT INTO transactions (transaction_id, user_id, category_name, expenses, descriptions, expense_date)
    VALUES (seq_transaction_id.NEXTVAL, p_user_id, p_category_name, p_expenses, p_description, SYSDATE);
    
    -- Récupérer l'ID de la catégorie
    SELECT category_id INTO v_category_id
    FROM categories
    WHERE category_name = p_category_name AND user_id = p_user_id;
    
    -- Mettre à jour le montant de la catégorie
    UPDATE categories
    SET amount = amount + p_expenses
    WHERE category_id = v_category_id;
    
    -- Mettre à jour la balance de l'utilisateur
    SELECT balance INTO v_new_balance
    FROM users
    WHERE user_id = p_user_id;
    
    v_new_balance := v_new_balance - p_expenses;
    
    UPDATE users
    SET balance = v_new_balance
    WHERE user_id = p_user_id;

END;
/
