CCCPaste
using System;
using System.Collections.Generic;

namespace OOP_13
{
internal class Program
{
static void Main(string[] args)
{
Simulation simulation = new Simulation();
simulation.Run();
}
}

public class Part
{
public Part(string name, decimal price, decimal workPrice)
{
Name = name;
Price = price;
WorkPrice = workPrice;
}

public string Name { get; }
public decimal Price { get; }
public decimal WorkPrice { get; }

public override bool Equals(object obj)
{
return obj is Part part && Name == part.Name;
}

public override int GetHashCode()
{
return Name.GetHashCode();
}

public override string ToString()
{
return $"{Name} (Цена: {Price}р, Работа: {WorkPrice}р)";
}
}

public class CarPart
{
public CarPart(Part partDefinition, bool isBroken = false)
{
PartDefinition = partDefinition;
IsBroken = isBroken;
}

public Part PartDefinition { get; }
public bool IsBroken { get; set; }

public override string ToString()
{
string status = IsBroken ? "СЛОМАНА" : "ЦЕЛАЯ";
return $"{PartDefinition.Name} [{status}]";
}
}

public class Car
{
public Car(string model)
{
Model = model;
}

public string Model { get; }
public List<CarPart> Parts { get; } = new List<CarPart>();

public void AddPart(CarPart part)
{
Parts.Add(part);
}

public List<CarPart> GetBrokenParts()
{
List<CarPart> brokenParts = new List<CarPart>();

foreach (CarPart part in Parts)
{
if (part.IsBroken)
{
brokenParts.Add(part);
}
}

return brokenParts;
}

public bool IsFullyRepaired()
{
foreach (CarPart part in Parts)
{
if (part.IsBroken)
{
return false;
}
}

return true;
}

public void PrintStatus()
{
const int LineWidth = 20;

Console.WriteLine($"\n--- Машина: {Model} ---");
Console.WriteLine("Состояние деталей:");

for (int i = 0; i < Parts.Count; i++)
{
Console.WriteLine($" {i + 1}. {Parts[i]}");
}

Console.WriteLine(new string('-', LineWidth));
}
}

public class Warehouse
{
private Dictionary<Part, int> _stock = new Dictionary<Part, int>();

public void AddStock(Part part, int quantity)
{
if (_stock.ContainsKey(part))
{
_stock[part] += quantity;
}
else
{
_stock[part] = quantity;
}

Console.WriteLine($"[Склад] Добавлено: {part.Name} (x{quantity}). Всего на складе: {_stock[part]}");
}

public bool HasPart(Part part)
{
return _stock.ContainsKey(part) && _stock[part] > 0;
}

public bool TakePart(Part part)
{
if (HasPart(part))
{
_stock[part]--;
Console.WriteLine($"[Склад] Взята деталь: {part.Name}. Осталось: {_stock[part]}");

return true;
}

Console.WriteLine($"[Склад] ОШИБКА: Детали '{part.Name}' нет на складе.");
return false;
}

public void PrintStock()
{
const int LineWidth = 20;

Console.WriteLine("--- Состояние склада ---");

if (_stock.Count == 0)
{
Console.WriteLine("Склад пуст.");
return;
}

foreach (var entry in _stock)
{
Console.WriteLine($"{entry.Key.Name}: {entry.Value} шт.");
}

Console.WriteLine(new string('-', LineWidth));
}
}

public class AutoService
{
private const decimal RefusalFineBefore = 500m;
private const decimal RefusalFinePerPart = 150m;

private Queue<Car> _carQueue = new Queue<Car>();

public AutoService(decimal initialBalance)
{
Balance = initialBalance;
Console.WriteLine($"Автосервис открыт! Начальный баланс: {Balance}р.");
}

public decimal Balance { get; private set; }

public Warehouse Warehouse { get; } = new Warehouse();

public void AddCarToQueue(Car car)
{
_carQueue.Enqueue(car);
Console.WriteLine($"[Очередь] Машина '{car.Model}' добавлена в очередь.");
}

public void ServeNextCar()
{
const string AgreeRepairCommand = "1";
const string RefuseRepairsCommand = "2";

// bool isRunning = true;

if (_carQueue.Count == 0)
{
Console.WriteLine("В очереди нет машин. Сервис отдыхает.");

return;
}

Car currentCar = _carQueue.Dequeue();

Console.WriteLine($"\n======= Начинаем обслуживание машины: {currentCar.Model} =======");
currentCar.PrintStatus();
Console.WriteLine("Что делаем с машиной?");
Console.WriteLine($"{AgreeRepairCommand}. Начать ремонт");
Console.WriteLine($"{RefuseRepairsCommand}. Отказаться от ремонта (Штраф: " + RefusalFineBefore + "р)");

string choice = Console.ReadLine();

StartRepairProcess(currentCar);

if (choice == RefuseRepairsCommand)
{
HandleRefusal(currentCar, true);
return;
}
}

public void PrintServiceStatus()
{
const int LineWidth = 20;

Console.WriteLine("\n===== СТАТУС АВТОСЕРВИСА =====");
Console.WriteLine($"Текущий баланс: {Balance}р.");
Console.WriteLine($"Машин в очереди: {_carQueue.Count}");
Warehouse.PrintStock();
Console.WriteLine(new string('=', LineWidth));
}

private void StartRepairProcess(Car car)
{
const string RefuseRepairsCommand = "0";

bool repairInProgress = true;

while (repairInProgress && car.IsFullyRepaired() == false)
{
Console.WriteLine("\n--- Процесс ремонта ---");
car.PrintStatus();

Console.WriteLine("Доступные детали для замены (введите номер):");

for (int i = 0; i < car.Parts.Count; i++)
{
Console.WriteLine($" {i + 1}. {car.Parts[i]}");
}

Console.WriteLine($"{RefuseRepairsCommand}. Отказаться от ремонта (Штраф за непочиненные детали)");

if (int.TryParse(Console.ReadLine(), out int partIndex) == false || partIndex < 0 || partIndex > car.Parts.Count)
{
Console.WriteLine("Неверный ввод. Попробуйте снова.");
continue;
}

if (partIndex == 0)
{
HandleRefusal(car, false);
repairInProgress = false;
continue;
}

CarPart selectedPart = car.Parts[partIndex - 1];
Part partTypeToReplace = selectedPart.PartDefinition;

if (Warehouse.HasPart(partTypeToReplace) == false)
{
Console.WriteLine($"ОШИБКА: Детали '{partTypeToReplace.Name}' нет на складе! Выберите другую деталь.");
continue;
}

Warehouse.TakePart(partTypeToReplace);

if (selectedPart.IsBroken)
{
decimal payment = partTypeToReplace.Price + partTypeToReplace.WorkPrice;
Balance += payment;
selectedPart.IsBroken = false;

Console.WriteLine($"УСПЕХ: Деталь '{partTypeToReplace.Name}' заменена.");
Console.WriteLine($"Получено {payment}р. (Деталь: {partTypeToReplace.Price}р, Работа: {partTypeToReplace.WorkPrice}р)");
Console.WriteLine($"Новый баланс сервиса: {Balance}р.");
}
else
{
Console.WriteLine($"ВНИМАНИЕ: Заменена целая деталь '{partTypeToReplace.Name}'. Оплата не взимается.");
}
}

if (car.IsFullyRepaired())
{
Console.WriteLine($"\n======= РЕМОНТ ЗАВЕРШЕН: {car.Model} =======");
Console.WriteLine("Все детали исправны. Машина готова!");
}

Console.WriteLine($"Итоговый баланс сервиса: {Balance}р.");
}

private void HandleRefusal(Car car, bool beforeRepair)
{
if (beforeRepair)
{
Balance += RefusalFineBefore;
Console.WriteLine($"[Отказ] Клиент отказался до ремонта. Штраф {RefusalFineBefore}р. Баланс: {Balance}р.");
}
else
{
int brokenPartsCount = car.GetBrokenParts().Count;
decimal fine = brokenPartsCount * RefusalFinePerPart;
Balance += fine;

Console.WriteLine($"[Отказ] Клиент отказался во время ремонта. Непочиненных деталей: {brokenPartsCount}.");
Console.WriteLine($"Штраф {fine}р. Баланс: {Balance}р.");
}

Console.WriteLine($"Машина '{car.Model}' покидает сервис.");
}
}

public class Simulation
{
private readonly AutoService _autoService;
private readonly Part _engine;
private readonly Part _wheel;
private readonly Part _sparkPlug;

public Simulation()
{
_engine = new Part("Двигатель", 50000m, 10000m);
_wheel = new Part("Колесо", 5000m, 500m);
_sparkPlug = new Part("Свеча зажигания", 500m, 200m);
_autoService = new AutoService(100000m);
}

public void Run()
{
SetupWarehouse();

SetupCarQueue();

_autoService.PrintServiceStatus();

Console.WriteLine("\n>>> Начинаем обслуживание 1-й машины <<<");
_autoService.ServeNextCar();

Console.WriteLine("\n>>> Начинаем обслуживание 2-й машины <<<");
_autoService.ServeNextCar();

Console.WriteLine("\n>>> Начинаем обслуживание 3-й машины <<<");
_autoService.ServeNextCar();

Console.WriteLine("\n\n--- СИМУЛЯЦИЯ ЗАВЕРШЕНА ---");
_autoService.PrintServiceStatus();

Console.WriteLine("\nНажмите Enter для выхода.");
Console.ReadLine();
}

private void SetupWarehouse()
{
_autoService.Warehouse.AddStock(_engine, 2);
_autoService.Warehouse.AddStock(_wheel, 10);
_autoService.Warehouse.AddStock(_sparkPlug, 50);
}

private void SetupCarQueue()
{
Car car1 = new Car("Volvo XC90");
car1.AddPart(new CarPart(_engine, true));
car1.AddPart(new CarPart(_wheel, false));
car1.AddPart(new CarPart(_wheel, true));
car1.AddPart(new CarPart(_wheel, false));
car1.AddPart(new CarPart(_wheel, false));
car1.AddPart(new CarPart(_sparkPlug, false));

Car car2 = new Car("Lada Granta");
car2.AddPart(new CarPart(_engine, false));
car2.AddPart(new CarPart(_wheel, false));
car2.AddPart(new CarPart(_sparkPlug, true));
car2.AddPart(new CarPart(_sparkPlug, true));

Car car3 = new Car("BMW X5");
car3.AddPart(new CarPart(_engine, true));

_autoService.AddCarToQueue(car1);
_autoService.AddCarToQueue(car2);
_autoService.AddCarToQueue(car3);
}
}
}