[Telink] Fix TC-OPCREDS-3.6 and prevent writing to NVS during factory reset (#26784)

* [Telink] Added storage reset in case of fabric count == 0

Signed-off-by: Misha Tkachenko <misha.tkachenko@telink-semi.com>

* [Telink] Disable openthread before reset to prevent writing to NVS

Signed-off-by: Misha Tkachenko <misha.tkachenko@telink-semi.com>

* [Telink] remove commented code

* Restyled by clang-format

* [Telink]: Added a clear explanation for preventing NVS writing on shutdown

Signed-off-by: Misha Tkachenko <misha.tkachenko@telink-semi.com>

* [Telink]: Updated OpenThread finalization function

Signed-off-by: Misha Tkachenko <misha.tkachenko@telink-semi.com>

* Restyled by whitespace

---------

Signed-off-by: Misha Tkachenko <misha.tkachenko@telink-semi.com>
Co-authored-by: Misha Tkachenko <misha.tkachenko@telink-semi.com>
Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Misha Tkachenko <36621698+mishadesh@users.noreply.github.com>
diff --git a/examples/platform/telink/common/src/AppTaskCommon.cpp b/examples/platform/telink/common/src/AppTaskCommon.cpp
index 4297d3a..ec45f92 100644
--- a/examples/platform/telink/common/src/AppTaskCommon.cpp
+++ b/examples/platform/telink/common/src/AppTaskCommon.cpp
@@ -38,6 +38,11 @@
 #include <app/InteractionModelEngine.h>
 #endif
 
+#ifdef CONFIG_CHIP_FACTORY_RESET_ERASE_NVS
+#include <zephyr/fs/nvs.h>
+#include <zephyr/settings/settings.h>
+#endif
+
 using namespace chip::app;
 
 LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);
@@ -118,7 +123,47 @@
     {
         if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0)
         {
-            chip::Server::GetInstance().ScheduleFactoryReset();
+            ChipLogProgress(DeviceLayer, "Performing erasing of settings partition");
+
+#ifdef CONFIG_CHIP_FACTORY_RESET_ERASE_NVS
+            void * storage = nullptr;
+            int status     = settings_storage_get(&storage);
+
+            if (status == 0)
+            {
+                status = nvs_clear(static_cast<nvs_fs *>(storage));
+            }
+
+            if (!status)
+            {
+                status = nvs_mount(static_cast<nvs_fs *>(storage));
+            }
+
+            if (status)
+            {
+                ChipLogError(DeviceLayer, "Storage clearance failed: %d", status);
+            }
+#else
+            const CHIP_ERROR err = PersistedStorage::KeyValueStoreMgrImpl().DoFactoryReset();
+
+            if (err != CHIP_NO_ERROR)
+            {
+                ChipLogError(DeviceLayer, "Factory reset failed: %" CHIP_ERROR_FORMAT, err.Format());
+            }
+
+            ConnectivityMgr().ErasePersistentInfo();
+#endif
+        }
+    }
+};
+
+class PlatformMgrDelegate : public DeviceLayer::PlatformManagerDelegate
+{
+    void OnShutDown() override
+    {
+        if (ThreadStackManagerImpl().IsThreadEnabled())
+        {
+            ThreadStackManagerImpl().Finalize();
         }
     }
 };
@@ -240,6 +285,15 @@
     chip::app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&GetICDUtil());
 #endif
 
+    // We need to disable OpenThread to prevent writing to the NVS storage when factory reset occurs
+    // The OpenThread thread is running during factory reset. The nvs_clear function is called during
+    // factory reset, which makes the NVS storage innaccessible, but the OpenThread knows nothing
+    // about this and tries to store the parameters to NVS. Because of this the OpenThread need to be
+    // shut down before NVS. This delegate fixes the issue "Failed to store setting , ret -13",
+    // which means that the NVS is already disabled.
+    // For this the OnShutdown function is used
+    PlatformMgr().SetDelegate(new PlatformMgrDelegate);
+
     // Add CHIP event handler and start CHIP thread.
     // Note that all the initialization code should happen prior to this point to avoid data races
     // between the main and the CHIP threads.
diff --git a/src/platform/telink/ThreadStackManagerImpl.cpp b/src/platform/telink/ThreadStackManagerImpl.cpp
index d6657c4..e66735b 100644
--- a/src/platform/telink/ThreadStackManagerImpl.cpp
+++ b/src/platform/telink/ThreadStackManagerImpl.cpp
@@ -136,5 +136,10 @@
     return CHIP_NO_ERROR;
 }
 
+void ThreadStackManagerImpl::Finalize(void)
+{
+    otInstanceFinalize(openthread_get_default_instance());
+}
+
 } // namespace DeviceLayer
 } // namespace chip
diff --git a/src/platform/telink/ThreadStackManagerImpl.h b/src/platform/telink/ThreadStackManagerImpl.h
index 870ea17..5083823 100644
--- a/src/platform/telink/ThreadStackManagerImpl.h
+++ b/src/platform/telink/ThreadStackManagerImpl.h
@@ -64,6 +64,7 @@
     CHIP_ERROR _InitThreadStack();
     void SetRadioBlocked(bool state) { mRadioBlocked = state; }
     bool IsReadyToAttach(void) const { return mReadyToAttach; }
+    void Finalize(void);
 
 protected:
     // ===== Methods that implement the ThreadStackManager abstract interface.