<reponame>sgdvesus/pycrud
import os
import sys
import csv
from typing import Dict, List, Optional, TypedDict, Any, Union

class ClientType(TypedDict):
    name: str
    company: str
    position: str
    email: str
    phone: int
    

main_menu: str = """
What are you doing?
[C] Create a new client
[R] Read client\'s list
[U] Update a client\'s fields
[D] Delete a client
[Exit]
"""

fields: str = """
Which field do you want to update?
[0] All
[1] Name
[2] Company
[3] Position
[4] Email
[5] Phone
""" 

CLIENT_TABLE: str = '.clients.csv'
CLIENT_TABLE_TEM: str = f'{CLIENT_TABLE}.tmp'
CLIENT_SCHEMA: List[str] = ['name', 'company', 'position', 'email', 'phone']
list_of_clients: List = []


def load_database() -> None:
    try:
        """Load database"""
        with open(CLIENT_TABLE, mode='r') as f:
            reader = csv.DictReader(f, fieldnames=CLIENT_SCHEMA)
            for row in reader:
                list_of_clients.append(row)
    except FileNotFoundError:
        print('Database no exite. Creando database. Try again...')
        with open(CLIENT_TABLE, mode='w'):
            pass


def save_database() -> None:
    """Save database."""
    with open(CLIENT_TABLE_TEM, mode='w') as f:
        writer = csv.DictWriter(f, fieldnames=CLIENT_SCHEMA)
        writer.writerows(list_of_clients)
        os.remove(CLIENT_TABLE)
        os.rename(CLIENT_TABLE_TEM, CLIENT_TABLE)

        
def _get_details(field: str, number: Optional[bool] = False) -> Any:
    user: str = input(f'What is the client {field}?\n')
    assert len(user) >= 1, "You cannot save an empty field. Try again..."
    if number:
        assert user.isnumeric() == True, "Error. You can only enter numbers. Try again..."
        if "number" in field:
            assert len(user) == 10, "Error. Enter a 10 digits number"        
        return int(user)
    
    return user


def _get_update_field(user: ClientType, all_fields: Optional[bool] = False) -> None:
    user_field: int = int(input(fields))
    
    assert user_field >= 0 and user_field <= 5,"Error. Not a valid option. Try again..."

    if user_field == 0:
        all_fields = True

    if user_field == 1 or all_fields:
        user['name'] = _get_details('updated name')

    if user_field == 2 or all_fields:
        user['company'] = _get_details('update company')

    if user_field == 3 or all_fields:
        user['position'] = _get_details('updated position')

    if user_field == 4 or all_fields:
        user['email'] = _get_details('updated email')

    if user_field == 5 or all_fields:
        user['phone'] = _get_details('updated phone', True)


def create_new_client() -> None:
    """Create a new client"""
    new_client: ClientType = {
        'name': _get_details('name'),
        'company': _get_details('company'),
        'position': _get_details('position'),
        'email': _get_details('email'),
        'phone': _get_details('phone number', True)
    }
    list_of_clients.append(new_client)
    print('New client created successfully!')


def read_all_clients() -> None:
    """Show all clients fields"""
    print("ID | name | company | position | email | phone")
    for client in list_of_clients:
        print(f'{list_of_clients.index(client)} | {client["name"]} | {client["company"]} | {client["position"]} | {client["email"]} | {client["phone"]}')


def update_client()-> None:
    """Updated a client fields"""
    try:
        uid: int = _get_details('ID', True)
        current_user: ClientType = list_of_clients[uid]
        _get_update_field(current_user)
        print('User Updated!')
    except ValueError:
        print('Not a valid command. Try again')
    except AssertionError as ae:
        print(ae)


def delete_client() -> None:
    """Deleted a client"""
    uid: int = _get_details('ID', True)
    list_of_clients.remove(list_of_clients[uid])
    print(f'Deleted client id:{uid}')


if __name__ == '__main__':
    load_database()
    user_option: str = input(main_menu).upper()
    if user_option == 'C':
        try: 
            create_new_client()    
        except AssertionError as ae:
            print(ae)
    elif user_option == 'R':
        try:
            read_all_clients()
        except Exception as e:
            print(e)
    elif user_option == 'U':
        try:
            update_client()
        except IndexError:
            print('Error. Client ID not valid. Try again...')
    elif user_option == 'D':
        try:
            delete_client()
        except IndexError:
            print('Error. Client ID not valid. Try again...')
    elif user_option == 'EXIT':
        sys.exit()
    save_database()
    
